@semiont/core 0.5.26 → 0.5.27
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/{chunk-FMFOBVTE.js → chunk-CUPZGI7I.js} +8 -3
- package/dist/chunk-CUPZGI7I.js.map +1 -0
- package/dist/{chunk-XQTWEBJ5.js → chunk-JWTQJVKM.js} +35 -27
- package/dist/chunk-JWTQJVKM.js.map +1 -0
- package/dist/{chunk-I3ZOWCTH.js → chunk-PPUO5IPX.js} +6 -5
- package/dist/chunk-PPUO5IPX.js.map +1 -0
- package/dist/config/node-config-loader.d.ts +2 -2
- package/dist/config/node-config-loader.js +1 -1
- package/dist/index.d.ts +197 -65
- package/dist/index.js +20 -9
- package/dist/index.js.map +1 -1
- package/dist/testing/axioms.js +2 -2
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-FMFOBVTE.js.map +0 -1
- package/dist/chunk-I3ZOWCTH.js.map +0 -1
- package/dist/chunk-XQTWEBJ5.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/identifiers.ts","../src/persisted-events.ts","../src/bus-protocol.ts","../src/event-utils.ts","../src/operators/burst-buffer.ts","../src/serialize-per-key.ts","../src/logger.ts","../src/annotation-utils.ts","../src/id-generation.ts","../src/annotation-assembly.ts","../src/web-annotation-utils.ts","../src/pdf-coordinates.ts","../src/pdf-anchoring.ts","../src/pdf-citation-search.ts","../src/resource-utils.ts","../src/errors.ts","../src/bus-request.ts","../src/fuzzy-anchor.ts","../src/anchor-annotation.ts","../src/locales.ts","../src/svg-utils.ts","../src/text-context.ts","../src/text-encoding.ts","../src/validation.ts","../src/media-types.ts","../src/chunking.ts","../src/type-guards.ts","../src/did-utils.ts","../src/config/environment-validator.ts","../src/config/configuration-error.ts","../src/config/platform-types.ts","../src/knowledge-graph-views.ts","../src/retry.ts","../src/shard-utils.ts","../src/discovery.ts"],"names":["resourceUri","baseUrl","annotationUri","right","map","ctx","start","end","email"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Branded identifier types for compile-time type safety.\n *\n * These types prevent mixing up resource IDs, annotation IDs, and user IDs\n * at compile time while having zero runtime overhead.\n *\n * URI types (ResourceUri, AnnotationUri) are in @semiont/http-transport\n * since they deal with HTTP URIs returned by the API.\n */\n\n// Branded type definitions for IDs only\nexport type ResourceId = string & { readonly __brand: 'ResourceId' };\nexport type AnnotationId = string & { readonly __brand: 'AnnotationId' };\nexport type UserId = string & { readonly __brand: 'UserId' };\n\n// Type guards with runtime validation\nexport function isResourceId(value: string): value is ResourceId {\n return !value.includes('/');\n}\n\nexport function isAnnotationId(value: string): value is AnnotationId {\n return !value.includes('/');\n}\n\n// Factory functions with runtime validation\nexport function resourceId(id: string): ResourceId {\n if (id.includes('/')) {\n throw new TypeError(`Expected ResourceId, got URI: ${id}`);\n }\n return id as ResourceId;\n}\n\nexport function annotationId(id: string): AnnotationId {\n if (id.includes('/')) {\n throw new TypeError(`Expected AnnotationId, got URI: ${id}`);\n }\n return id as AnnotationId;\n}\n\nexport function userId(id: string): UserId {\n return id as UserId;\n}\n","/**\n * Persisted Events\n *\n * The event types that get appended to the JSONL event log.\n * Each maps a type string to its OpenAPI payload schema.\n * The PersistedEvent union derives from this catalog.\n */\n\nimport type { components } from './types';\nimport type { AnnotationId, ResourceId } from './identifiers';\nimport type { Annotation } from './annotation-types';\nimport type { EventBase } from './event-base';\n\n// Branded payload overrides — the OpenAPI schemas reference the raw\n// `Annotation` type with `id: string`. At the TypeScript layer we narrow\n// to the branded `Annotation` so consumers read `payload.annotation.id`\n// as `AnnotationId` without an upcast at every seam.\ntype AnnotationAddedPayload =\n components['schemas']['AnnotationAddedPayload'] & { annotation: Annotation };\ntype AnnotationRemovedPayload =\n components['schemas']['AnnotationRemovedPayload'] & { annotationId: AnnotationId };\ntype AnnotationBodyUpdatedPayload =\n components['schemas']['AnnotationBodyUpdatedPayload'] & { annotationId: AnnotationId };\n\n// ── The Catalog ──────────────────────────────────────────────────────────────\n\n/**\n * Maps each persisted event type string to its OpenAPI payload schema.\n * Single source of truth for \"what events get written to the log.\"\n */\ntype PersistedEventCatalog = {\n 'yield:created': components['schemas']['ResourceCreatedPayload'];\n 'yield:cloned': components['schemas']['ResourceClonedPayload'];\n 'yield:updated': components['schemas']['ResourceUpdatedPayload'];\n 'yield:moved': components['schemas']['ResourceMovedPayload'];\n 'yield:representation-added': components['schemas']['RepresentationAddedPayload'];\n 'yield:representation-removed': components['schemas']['RepresentationRemovedPayload'];\n 'mark:added': AnnotationAddedPayload;\n 'mark:removed': AnnotationRemovedPayload;\n 'mark:body-updated': AnnotationBodyUpdatedPayload;\n 'mark:archived': components['schemas']['ResourceArchivedPayload'];\n 'mark:unarchived': components['schemas']['ResourceUnarchivedPayload'];\n 'mark:entity-tag-added': components['schemas']['EntityTagChangedPayload'];\n 'mark:entity-tag-removed': components['schemas']['EntityTagChangedPayload'];\n 'frame:entity-type-added': components['schemas']['EntityTypeAddedPayload'];\n 'frame:tag-schema-added': components['schemas']['TagSchemaAddedPayload'];\n 'job:started': components['schemas']['JobStartedPayload'];\n 'job:progress': components['schemas']['JobProgressPayload'];\n 'job:completed': components['schemas']['JobCompletedPayload'];\n 'job:failed': components['schemas']['JobFailedPayload'];\n};\n\n// ── Derived types ────────────────────────────────────────────────────────────\n\n/** System event types — persisted events that have no resourceId. */\ntype SystemEventType = 'frame:entity-type-added' | 'frame:tag-schema-added';\n\n/** Extract the concrete persisted event type for a given type string. */\nexport type EventOfType<K extends keyof PersistedEventCatalog> =\n K extends SystemEventType\n ? EventBase & { type: K; payload: PersistedEventCatalog[K] }\n : EventBase & { type: K; resourceId: ResourceId; payload: PersistedEventCatalog[K] };\n\n/** The union of all persisted event types. Discriminated on `type`. */\nexport type PersistedEvent = {\n [K in keyof PersistedEventCatalog]: EventOfType<K>\n}[keyof PersistedEventCatalog];\n\nexport type PersistedEventType = PersistedEvent['type'];\n\n/**\n * Runtime list of every persisted event type.\n *\n * Single source of truth for code that needs to enumerate event types at\n * runtime — most importantly the per-resource `events-stream` SSE route,\n * which subscribes to all of them. The exhaustiveness check below makes\n * it impossible to add a new member to `PersistedEventCatalog` without\n * also adding it here: forgetting fails to typecheck rather than silently\n * dropping the event from the events-stream.\n */\nexport const PERSISTED_EVENT_TYPES = [\n 'yield:created',\n 'yield:cloned',\n 'yield:updated',\n 'yield:moved',\n 'yield:representation-added',\n 'yield:representation-removed',\n 'mark:added',\n 'mark:removed',\n 'mark:body-updated',\n 'mark:archived',\n 'mark:unarchived',\n 'mark:entity-tag-added',\n 'mark:entity-tag-removed',\n 'frame:entity-type-added',\n 'frame:tag-schema-added',\n 'job:started',\n 'job:progress',\n 'job:completed',\n 'job:failed',\n] as const satisfies readonly PersistedEventType[];\n\n// Compile-time exhaustiveness: if PersistedEventType gains a member that\n// PERSISTED_EVENT_TYPES is missing, this assignment fails to typecheck.\n// The ERROR object names the missing-member case so the build error is\n// self-explanatory.\ntype _ExhaustivePersistedEventTypes =\n Exclude<PersistedEventType, typeof PERSISTED_EVENT_TYPES[number]> extends never\n ? true\n : { ERROR: 'PERSISTED_EVENT_TYPES is missing members of PersistedEventType' };\nconst _persistedEventTypesExhaustive: _ExhaustivePersistedEventTypes = true;\nvoid _persistedEventTypesExhaustive;\n\n/** Input type for appendEvent — PersistedEvent without id/timestamp (assigned at persistence time). */\nexport type EventInput = Omit<PersistedEvent, 'id' | 'timestamp'>;\n","// ⚠ GENERATED FILE — do not edit.\n//\n// Authority: specs/src/bus/registry.json (channels, payloads, operations)\n// Regenerate: node scripts/bus/generate-ts.mjs\n// Go counterpart: node scripts/bus/generate-go.mjs → packages/sdk-go/bus\n//\n// Payload schemas themselves live in the OpenAPI components; the registry\n// names which one each channel carries. Add or change a channel THERE.\n\n/**\n * Bus Protocol\n *\n * The complete EventMap for the RxJS EventBus. Every channel name and\n * its payload type is defined here — domain events, commands, reads,\n * results, SSE stream payloads, and frontend UI events.\n *\n * Identifier discipline: where a payload carries an annotation or\n * resource id, the TypeScript layer narrows the OpenAPI `string` to the\n * branded type (`AnnotationId`, `ResourceId`, `UserId`). The runtime\n * wire shape is unchanged (brands have no runtime representation);\n * what this buys us is that command handlers don't have to re-brand\n * at every seam. Brand once at the entry boundary (HTTP route handler,\n * DOM attribute read, URL param parse), not at every bus hop in\n * between. See `.plans/BRAND-UPSTREAM.md` for the rationale.\n *\n * Organized by flow (verb), then by category within each flow.\n */\n\nimport type { components } from './types';\nimport type { AnnotationId, ResourceId } from './identifiers';\nimport type { Annotation } from './annotation-types';\nimport type { ResourceDescriptor } from './graph';\nimport type { StoredEvent } from './event-base';\nimport type { EventOfType } from './persisted-events';\nimport type { AnchorRect } from './bus-ui-types';\n\n// Branded overrides for OpenAPI command payloads that carry identifier\n// fields. Narrows `string` → branded at the TypeScript layer.\n//\n// `_userId` is the gateway-injected authenticated DID (string at the\n// schema layer); handlers that need a `UserId` brand it locally.\ntype MarkDeleteCommand =\n components['schemas']['MarkDeleteCommand'] & {\n annotationId: AnnotationId;\n resourceId?: ResourceId;\n };\ntype MarkUpdateBodyCommand =\n components['schemas']['MarkUpdateBodyCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\ntype BindInitiateCommand =\n components['schemas']['BindInitiateCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\ntype BindUpdateBodyCommand =\n components['schemas']['BindUpdateBodyCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\n\n/**\n * The unified EventMap — every channel on the EventBus.\n *\n * Convention:\n * - Domain events (past tense): StoredEvent<Interface> — branded types\n * - Commands/reads/results/UI: OpenAPI schema refs — plain strings\n * - void: UI-only signals with no payload\n */\n\n\nexport type EventMap = {\n\n // ========================================================================\n // YIELD FLOW — resource creation, update, move, clone\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'yield:created': StoredEvent<EventOfType<'yield:created'>>;\n 'yield:cloned': StoredEvent<EventOfType<'yield:cloned'>>;\n 'yield:updated': StoredEvent<EventOfType<'yield:updated'>>;\n 'yield:moved': StoredEvent<EventOfType<'yield:moved'>>;\n 'yield:representation-added': StoredEvent<EventOfType<'yield:representation-added'>>;\n 'yield:representation-removed': StoredEvent<EventOfType<'yield:representation-removed'>>;\n\n // Generation lifecycle flows through the unified job:* family\n // (job:start, job:report-progress, job:complete, job:fail). The\n // pre-unification `yield:progress`/`yield:finished`/`yield:failed`\n // channels were removed on the lifecycle-unification.\n\n // Commands\n 'yield:create': components['schemas']['YieldCreateCommand'];\n 'yield:update': components['schemas']['YieldUpdateCommand'];\n 'yield:mv': components['schemas']['YieldMvCommand'];\n 'yield:clone': void;\n 'yield:clone-token-requested': components['schemas']['YieldCloneTokenRequest'];\n 'yield:clone-resource-requested': components['schemas']['YieldCloneResourceRequest'];\n 'yield:clone-create': components['schemas']['YieldCloneCreateCommand'];\n\n // Command results\n 'yield:create-ok': components['schemas']['YieldCreateOk'];\n 'yield:create-failed': components['schemas']['CommandError'];\n 'yield:update-ok': components['schemas']['YieldUpdateOk'];\n 'yield:update-failed': components['schemas']['CommandError'];\n 'yield:move-failed': { fromUri: string } & components['schemas']['CommandError'];\n 'yield:clone-token-generated': { correlationId: string; response: components['schemas']['CloneResourceWithTokenResponse'] };\n 'yield:clone-token-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'yield:clone-resource-result': { correlationId: string; response: components['schemas']['GetResourceByTokenResponse'] };\n 'yield:clone-resource-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'yield:clone-created': components['schemas']['YieldCloneCreated'];\n 'yield:clone-create-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // ========================================================================\n // MARK FLOW — annotation CRUD, AI assist, resource lifecycle\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'mark:added': StoredEvent<EventOfType<'mark:added'>>;\n 'mark:removed': StoredEvent<EventOfType<'mark:removed'>>;\n 'mark:body-updated': StoredEvent<EventOfType<'mark:body-updated'>>;\n 'mark:entity-tag-added': StoredEvent<EventOfType<'mark:entity-tag-added'>>;\n 'mark:entity-tag-removed': StoredEvent<EventOfType<'mark:entity-tag-removed'>>;\n 'mark:archived': StoredEvent<EventOfType<'mark:archived'>>;\n 'mark:unarchived': StoredEvent<EventOfType<'mark:unarchived'>>;\n\n // Annotation-job lifecycle flows through the unified job:* family\n // (job:start, job:report-progress, job:complete, job:fail). UI\n // consumers filter by jobType. The pre-unification channels\n // `mark:progress`/`mark:assist-finished`/`mark:assist-failed` were\n // removed on the lifecycle-unification.\n\n // Commands\n 'mark:create-request': components['schemas']['MarkCreateRequest'];\n 'mark:create': components['schemas']['MarkCreateCommand'];\n 'mark:delete': MarkDeleteCommand;\n 'mark:update-body': MarkUpdateBodyCommand;\n 'mark:archive': components['schemas']['MarkArchiveCommand'];\n 'mark:unarchive': components['schemas']['MarkUnarchiveCommand'];\n 'mark:update-entity-types': components['schemas']['MarkUpdateEntityTypesCommand'];\n\n // Command results\n 'mark:create-ok': components['schemas']['MarkCreateOk'];\n 'mark:create-failed': components['schemas']['CommandError'];\n 'mark:delete-ok': components['schemas']['MarkDeleteOk'];\n 'mark:delete-failed': components['schemas']['CommandError'];\n // archive/unarchive confirmed-write replies (bridged) — correlation-keyed\n // acks the SDK's busRequest awaits. Failure routes the real outcome back\n // instead of the old fire-and-forget silence (.plans/bugs/BRIDGE-GAPS.md).\n 'mark:archive-ok': { correlationId?: string };\n 'mark:archive-failed': components['schemas']['CommandError'];\n 'mark:unarchive-ok': { correlationId?: string };\n 'mark:unarchive-failed': components['schemas']['CommandError'];\n // update-entity-types confirmed-write reply (bridged) — correlation-keyed ack\n // the SDK's busRequest awaits; failure routes the real outcome back rather than\n // the old fire-and-forget silence (.plans/bugs/BRIDGE-GAPS.md).\n 'mark:update-entity-types-ok': { correlationId?: string };\n 'mark:update-entity-types-failed': components['schemas']['CommandError'];\n 'mark:body-update-failed': components['schemas']['CommandError'];\n\n // UI events\n 'mark:select-comment': components['schemas']['SelectionData'];\n 'mark:select-tag': components['schemas']['SelectionData'];\n 'mark:select-assessment': components['schemas']['SelectionData'];\n 'mark:select-reference': components['schemas']['SelectionData'];\n 'mark:requested': components['schemas']['MarkRequestedEvent'];\n 'mark:cancel-pending': void;\n 'mark:submit': components['schemas']['MarkSubmitEvent'];\n 'mark:assist-request': components['schemas']['MarkAssistRequestEvent'];\n 'mark:progress-dismiss': void;\n // Client-local: the assist Observable went silent past its deadline (no\n // progress, no completion, no job:fail). Emitted by mark-state-unit so the\n // outcome-notification layer can tell the user; a real job failure arrives\n // as job:fail instead and never produces this.\n 'mark:assist-timeout': { resourceId: string; motivation: components['schemas']['Motivation'] };\n // Client-local UI notifications for annotation command failures, emitted by\n // the awaiting catch (mark-state-unit), which inherently knows whose command\n // failed on which resource. Distinct from the `mark:create-failed` /\n // `mark:delete-failed` wire replies above: those are busRequest correlation\n // plumbing (CommandError, matched by correlationId, bridged to every\n // client) and are NOT for UI consumption — subscribing to them raw\n // double-toasts the requester and leaks other users' failures.\n 'mark:create-error': { resourceId: string; message: string };\n 'mark:delete-error': { resourceId: string; message: string };\n // Same pattern for bind body updates initiated by callers that cannot toast\n // directly (e.g. ReferenceEntry's unlink); awaiting callers with their own\n // toast surface (the reference wizard) surface failures themselves instead.\n 'bind:body-error': { resourceId: string; message: string };\n\n // ========================================================================\n // FRAME FLOW — schema-layer vocabulary (entity types; future tag schemas,\n // relation/predicate types, ontology import). The eighth flow.\n // ========================================================================\n\n // Domain events (branded — system of record). System-level: no resourceId.\n 'frame:entity-type-added': StoredEvent<EventOfType<'frame:entity-type-added'>>;\n 'frame:tag-schema-added': StoredEvent<EventOfType<'frame:tag-schema-added'>>;\n\n // Commands\n 'frame:add-entity-type': components['schemas']['FrameAddEntityTypeCommand'];\n 'frame:add-tag-schema': components['schemas']['FrameAddTagSchemaCommand'];\n\n // Command results — `*-add-ok` / `*-add-failed` are correlation-keyed replies\n // for the SDK's confirmed `busRequest` writes (both bridged). In-process callers\n // (bootstrap/replay/import) instead race the `frame:*-added` domain event and\n // don't await `*-add-ok`, so its correlationId is optional.\n 'frame:entity-type-add-ok': { correlationId?: string };\n 'frame:entity-type-add-failed': components['schemas']['CommandError'];\n 'frame:tag-schema-add-ok': { correlationId?: string };\n 'frame:tag-schema-add-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // BIND FLOW — reference linking\n // ========================================================================\n\n 'bind:initiate': BindInitiateCommand;\n 'bind:update-body': BindUpdateBodyCommand;\n 'bind:body-updated': components['schemas']['BindBodyUpdated'];\n 'bind:body-update-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // MATCH FLOW — search\n // ========================================================================\n\n 'match:search-requested': components['schemas']['MatchSearchRequest'];\n 'match:search-results': components['schemas']['MatchSearchResult'];\n 'match:search-failed': components['schemas']['MatchSearchFailed'];\n\n // ========================================================================\n // GATHER FLOW — context gathering\n // ========================================================================\n\n 'gather:requested': components['schemas']['GatherAnnotationRequest'];\n 'gather:complete': components['schemas']['GatherAnnotationComplete'];\n 'gather:failed': { correlationId: string; annotationId: string } & components['schemas']['CommandError'];\n 'gather:resource-requested': components['schemas']['GatherResourceRequest'];\n 'gather:resource-complete': components['schemas']['GatherResourceComplete'];\n 'gather:resource-failed': { correlationId: string; resourceId: string } & components['schemas']['CommandError'];\n\n 'gather:summary-requested': components['schemas']['GatherSummaryRequest'];\n 'gather:summary-result': { correlationId: string; response: Record<string, unknown> };\n 'gather:summary-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // SSE stream payloads\n 'gather:annotation-progress': components['schemas']['GatherProgress'];\n\n // ========================================================================\n // BROWSE FLOW — knowledge base reads + UI navigation\n // ========================================================================\n\n // Reads.\n //\n // Reply `response` payloads carry DOMAIN-flavored documents: the KS serves\n // real, validated ids, so these declare the branded `Annotation` /\n // `ResourceDescriptor` (annotation-types.ts / graph.ts) rather than the raw\n // OpenAPI flavors — consumers must never need to re-brand (`as Annotation[]`)\n // what the protocol already guarantees. Field overrides via Omit +\n // intersection; envelope shape per .plans/REPLY-SHAPE-STANDARD.md.\n 'browse:resource-requested': components['schemas']['BrowseResourceRequest'];\n 'browse:resource-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetResourceResponse'], 'resource' | 'annotations' | 'entityReferences'> & {\n resource: ResourceDescriptor;\n annotations: Annotation[];\n entityReferences: Annotation[];\n };\n };\n 'browse:resource-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // A resource's derived coordinate map — the text recovered from its bytes\n // plus the geometry that indexes it (ANCHORED-TEXT-CACHE Lane 5).\n //\n // Read-only over the wire: the Smelter is the sole producer and publishes\n // through `IContentTransport`, never over this channel. `null` in the reply\n // means no map has been derived, which is the common case and not an error.\n 'browse:anchored-text-requested': components['schemas']['BrowseAnchoredTextRequest'];\n 'browse:anchored-text-result': { correlationId: string; response: components['schemas']['ExtractionOutcome'] | null };\n 'browse:anchored-text-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:resources-requested': components['schemas']['BrowseResourcesRequest'];\n 'browse:resources-result': {\n correlationId: string;\n response: Omit<components['schemas']['ListResourcesResponse'], 'resources'> & {\n resources: ResourceDescriptor[];\n };\n };\n 'browse:resources-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotations-requested': components['schemas']['BrowseAnnotationsRequest'];\n 'browse:annotations-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetAnnotationsResponse'], 'annotations'> & {\n annotations: Annotation[];\n };\n };\n 'browse:annotations-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-requested': components['schemas']['BrowseAnnotationRequest'];\n 'browse:annotation-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetAnnotationResponse'], 'annotation' | 'resource' | 'resolvedResource'> & {\n annotation: Annotation;\n resource: ResourceDescriptor | null;\n resolvedResource: ResourceDescriptor | null;\n };\n };\n 'browse:annotation-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:events-requested': components['schemas']['BrowseEventsRequest'];\n 'browse:events-result': components['schemas']['BrowseEventsResult'];\n 'browse:events-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-history-requested': components['schemas']['BrowseAnnotationHistoryRequest'];\n 'browse:annotation-history-result': components['schemas']['BrowseAnnotationHistoryResult'];\n 'browse:annotation-history-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-context-requested': components['schemas']['BrowseAnnotationContextRequest'];\n 'browse:annotation-context-result': { correlationId: string; response: Record<string, unknown> };\n 'browse:annotation-context-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:referenced-by-requested': components['schemas']['BrowseReferencedByRequest'];\n 'browse:referenced-by-result': components['schemas']['BrowseReferencedByResult'];\n 'browse:referenced-by-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:entity-types-requested': components['schemas']['BrowseEntityTypesRequest'];\n 'browse:entity-types-result': components['schemas']['BrowseEntityTypesResult'];\n 'browse:entity-types-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:tag-schemas-requested': components['schemas']['BrowseTagSchemasRequest'];\n 'browse:tag-schemas-result': components['schemas']['BrowseTagSchemasResult'];\n 'browse:tag-schemas-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:agents-requested': components['schemas']['BrowseAgentsRequest'];\n 'browse:agents-result': components['schemas']['BrowseAgentsResult'];\n 'browse:agents-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:directory-requested': components['schemas']['BrowseDirectoryRequest'];\n 'browse:directory-result': components['schemas']['BrowseDirectoryResult'];\n 'browse:directory-failed': { correlationId: string; path: string } & components['schemas']['CommandError'];\n\n // UI events (session-scoped — fire on the client bus, tied to a KB)\n 'browse:click': components['schemas']['BrowseClickEvent'] & { anchorRect?: AnchorRect };\n 'browse:reference-navigate': components['schemas']['BrowseReferenceNavigateEvent'];\n 'browse:entity-type-clicked': components['schemas']['BrowseEntityTypeClickedEvent'];\n\n // ========================================================================\n // SHELL — app-scoped UI events (fire on SemiontBrowser's bus, not the\n // per-session client bus). These must work regardless of whether a\n // KB session is active: panel toggles, sidebar, tab bar, routing.\n // ========================================================================\n\n 'panel:toggle': components['schemas']['BrowsePanelToggleEvent'];\n 'panel:open': components['schemas']['BrowsePanelOpenEvent'] & { anchorRect?: AnchorRect };\n 'panel:close': void;\n 'shell:sidebar-toggle': void;\n 'tabs:close': components['schemas']['BrowseResourceCloseEvent'];\n 'tabs:reorder': components['schemas']['BrowseResourceReorderEvent'];\n 'nav:link-clicked': components['schemas']['BrowseLinkClickedEvent'];\n 'nav:push': components['schemas']['BrowseRouterPushEvent'];\n 'nav:external': components['schemas']['BrowseExternalNavigateEvent'] & { cancelFallback: () => void };\n\n // ========================================================================\n // BECKON FLOW — annotation attention\n // ========================================================================\n\n 'beckon:hover': components['schemas']['BeckonHoverEvent'];\n 'beckon:focus': components['schemas']['BeckonFocusEvent'];\n 'beckon:sparkle': components['schemas']['BeckonSparkleEvent'];\n\n // ========================================================================\n // JOB FLOW — worker commands + domain events\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'job:started': StoredEvent<EventOfType<'job:started'>>;\n 'job:progress': StoredEvent<EventOfType<'job:progress'>>;\n 'job:completed': StoredEvent<EventOfType<'job:completed'>>;\n 'job:failed': StoredEvent<EventOfType<'job:failed'>>;\n\n // Commands\n 'job:start': components['schemas']['JobStartCommand'];\n 'job:report-progress': components['schemas']['JobReportProgressCommand'];\n 'job:complete': components['schemas']['JobCompleteCommand'];\n 'job:fail': components['schemas']['JobFailCommand'];\n 'job:queued': components['schemas']['JobQueuedEvent'];\n 'job:cancel-requested': components['schemas']['JobCancelRequest'];\n 'job:status-requested': components['schemas']['JobStatusRequest'];\n 'job:create': components['schemas']['JobCreateCommand'];\n 'job:claim': components['schemas']['JobClaimCommand'];\n\n // Results\n 'job:status-result': components['schemas']['JobStatusResult'];\n 'job:status-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'job:created': components['schemas']['JobCreatedResult'];\n 'job:create-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'job:claimed': { correlationId: string; response: Record<string, unknown> };\n 'job:claim-failed': { correlationId: string } & components['schemas']['CommandError'];\n // cancel-by-type confirmed-write reply: the count of *pending* jobs cancelled\n // (running jobs finish — there's no worker-kill channel). Failure surfaces a\n // queue error instead of the old silent swallow (.plans/bugs/BRIDGE-GAPS.md).\n 'job:cancel-ok': { correlationId?: string; response: { cancelled: number } };\n 'job:cancel-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // WEAVE FLOW — graph projection progress (GRAPH-PROJECTION-SYNC, D2 = push)\n // ========================================================================\n\n /**\n * Emitted by the Weaver after applying an event (or a batch's last event)\n * for a resource to the graph. `sequenceNumber` is the resource-stream\n * sequence of the last applied event. Folded by `WeaveProgress`\n * (make-meaning) into the backend-local applied map that the\n * `whenApplied` barrier awaits. In-process signal today; crosses the\n * bus gateway after WEAVER-ISOLATION.\n */\n 'weave:applied': { resourceId: string; sequenceNumber: number };\n\n // Signal — the vector projection's per-resource decision report: emitted\n // by the Smelter after indexing a resource's content ('indexed') or after\n // deciding not to ('skipped', with a `reason` naming the decline — the\n // SMELTER-MEDIA-TYPES telemetry vocabulary: 'no-extractor' | 'empty' today,\n // the PDF decline classes when extraction lands). Keyed by the\n // checksum of the bytes inspected — \"settled at C\" is read-your-writes for\n // exactly that content. NEVER emitted on transient failures: an error is not\n // a decision (SMELTER-INDEX-SYNC A2). Consumed by the backend-local\n // `SmeltProgress` fold behind the gather-side barrier. This is the\n // Smelter's single outbound signal (SMELTER-AXIOMS D3, as amended).\n 'smelt:settled': { resourceId: string; contentChecksum: string; outcome: 'indexed' | 'skipped'; reason?: 'no-extractor' | 'empty' | 'no-text-layer' | 'encrypted' | 'corrupt' | 'too-large' };\n\n // Command — rebuild the graph projection from the event log (full when\n // resourceId is absent, one resource when present). Served by the Weaver;\n // replaces direct `rebuildAll()`/`rebuildResource()` access, which does\n // not survive the container split (WEAVER-ISOLATION D3). Correlated\n // request/reply via the BUS_OPERATIONS registry.\n 'weave:rebuild': components['schemas']['WeaveRebuildCommand'];\n 'weave:rebuild-ok': { correlationId?: string };\n 'weave:rebuild-failed': { correlationId?: string; message: string };\n\n // Command — rebuild anchored-text artifacts by re-running extraction\n // (every geometry-capable resource when resourceId is absent, one when\n // present). Served by the Smelter, serialized, never destructive, and\n // with ZERO embedding calls — only the derived map is re-made\n // (PERSIST-ANCHORS P0). Correlated request/reply via BUS_OPERATIONS.\n 'smelt:rebuild-anchors': components['schemas']['SmeltRebuildAnchorsCommand'];\n 'smelt:rebuild-anchors-ok': { correlationId?: string };\n 'smelt:rebuild-anchors-failed': { correlationId?: string; message: string };\n\n // ========================================================================\n // SETTINGS (frontend-only)\n // ========================================================================\n\n 'settings:theme-changed': components['schemas']['SettingsThemeChangedEvent'];\n 'settings:line-numbers-toggled': void;\n 'settings:locale-changed': components['schemas']['SettingsLocaleChangedEvent'];\n 'settings:hover-delay-changed': components['schemas']['SettingsHoverDelayChangedEvent'];\n\n // ========================================================================\n // SSE infrastructure\n // ========================================================================\n\n 'stream-connected': Record<string, never>;\n 'replay-window-exceeded': { resourceId?: string; lastEventId: number; missedCount: number; cap: number; message: string };\n /**\n * Emitted by the `/bus/subscribe` handler when a client reconnected\n * with `Last-Event-ID: p-<scope>-<seq>` but the server could not\n * replay all missed persisted events for that scope (retention\n * window exceeded, scope unknown, or request unparseable). The\n * client should treat this as a signal to fall back to the pre-\n * resumption contract: invalidate caches for the affected scope\n * and re-read from scratch. Analogous to `replay-window-exceeded`\n * but scoped to the bus gateway rather than the per-resource\n * events stream.\n *\n * `scope` is the scope string the client asked about (omitted for\n * global-persisted resumption gaps, if that path ever exists).\n * `reason` is human-readable, for logging.\n */\n 'bus:resume-gap': { scope?: string; lastSeenId?: string; reason: string };\n};\n\nexport type { AnchorRect } from './bus-ui-types';\n\n/**\n * Any valid channel name on the EventBus — `keyof EventMap`, the root channel\n * type. Two subsets matter, and confusing them is a silent-failure trap:\n *\n * - `EmittableChannel` (below) — channels with a non-null `CHANNEL_SCHEMAS`\n * entry; what you EMIT (the `/bus/emit` gateway validates the payload).\n * - `BridgedChannel` (`bridged-channels.ts`) — the transport fan-in set; the\n * only channels a client can SUBSCRIBE to over a concrete transport.\n *\n * Request/reply (`busRequest`) emits on an `EmittableChannel` and subscribes on\n * `BridgedChannel` replies. A reply channel that is a valid `EventName` but NOT\n * in `BRIDGED_CHANNELS` is never delivered → the request times out with no\n * compile or runtime error (see\n * `.plans/bugs/gather-resource-complete-not-bridged.md`). `busRequest` now types\n * its reply params `BridgedChannel` so that omission is a compile error.\n */\nexport type EventName = keyof EventMap;\n\n/**\n * Genuine resource-bound broadcast event types.\n *\n * Publishers emit these on the scoped EventBus (`eventBus.scope(resourceId)`)\n * because every participant viewing the resource should receive them — not\n * just the caller who triggered the originating action. Examples: resource\n * generation progress, which multiple viewers of a generating resource all\n * want to see.\n *\n * Non-broadcast progress (AI-assist progress for one user, search results\n * for one caller) does NOT belong here. Those are per-caller correlation-ID\n * responses and publish globally — the caller filters by `correlationId`.\n *\n * The SDK's resource-scoped `browse.*` live queries wire these channels —\n * subscribing acquires the scope via the transport's `subscribeToResource`\n * (`scope=id&scoped=<channel>`) so the SSE route delivers them to that\n * participant (freshness follows observation; #847). WorkerStateUnit uses this\n * list to decide which emitted events to scope to their resource.\n */\nexport const RESOURCE_BROADCAST_TYPES = [\n // Currently empty. `job:complete` / `job:fail` were moved to GLOBAL,\n // `jobId`-keyed correlation delivery (#847): the dispatching caller\n // filters by `jobId`, and resource viewers filter the same global stream\n // by `resourceId` — no resource-scoped copy, so a client that is both\n // dispatcher and viewer no longer receives it twice. This set remains as\n // the extension point for *genuine* resource-bound broadcasts — events\n // every viewer of a resource should see and no single caller owns (e.g.\n // resource-generation progress for multiple viewers).\n] as const satisfies readonly EventName[];\n\nexport type ResourceBroadcastType = typeof RESOURCE_BROADCAST_TYPES[number];\n\n/**\n * Authoritative map from bus channel to OpenAPI schema name.\n *\n * Every {@link EventName} must appear. The `satisfies` clause below\n * enforces completeness at compile time — adding a channel to\n * {@link EventMap} without adding an entry here is a build error.\n *\n * Values:\n * - `<SchemaName>`: payload validates against `components['schemas'][SchemaName]`.\n * - `null`: no single-schema validation. Used for branded\n * `StoredEvent` wrappers, `void` UI signals, and compound inline\n * types (e.g. `{ correlationId } & CommandError`). These are not\n * validated by `/bus/emit`.\n *\n * The `/bus/emit` route reads this map to validate incoming payloads.\n * Consumers can also use it to do client-side pre-flight validation\n * before emitting.\n */\nexport const CHANNEL_SCHEMAS = {\n // ── YIELD FLOW ──────────────────────────────────────────────────\n 'yield:created': null, // StoredEvent\n 'yield:cloned': null,\n 'yield:updated': null,\n 'yield:moved': null,\n 'yield:representation-added': null,\n 'yield:representation-removed': null,\n 'yield:create': 'YieldCreateCommand',\n 'yield:update': 'YieldUpdateCommand',\n 'yield:mv': 'YieldMvCommand',\n 'yield:clone': null, // void\n 'yield:clone-token-requested': 'YieldCloneTokenRequest',\n 'yield:clone-resource-requested': 'YieldCloneResourceRequest',\n 'yield:clone-create': 'YieldCloneCreateCommand',\n 'yield:create-ok': 'YieldCreateOk',\n 'yield:create-failed': 'CommandError',\n 'yield:update-ok': 'YieldUpdateOk',\n 'yield:update-failed': null, // { correlationId } & CommandError\n 'yield:move-failed': null, // { fromUri } & CommandError\n 'yield:clone-token-generated': null, // { correlationId; response: CloneResourceWithTokenResponse }\n 'yield:clone-token-failed': null, // { correlationId } & CommandError\n 'yield:clone-resource-result': null, // { correlationId; response: GetResourceByTokenResponse }\n 'yield:clone-resource-failed': null, // { correlationId } & CommandError\n 'yield:clone-created': 'YieldCloneCreated',\n 'yield:clone-create-failed': null, // { correlationId } & CommandError\n\n // ── MARK FLOW ───────────────────────────────────────────────────\n 'mark:added': null, // StoredEvent\n 'mark:removed': null,\n 'mark:body-updated': null,\n 'mark:entity-tag-added': null,\n 'mark:entity-tag-removed': null,\n 'frame:entity-type-added': null,\n 'frame:tag-schema-added': null,\n 'mark:archived': null,\n 'mark:unarchived': null,\n 'mark:create-request': 'MarkCreateRequest',\n 'mark:create': 'MarkCreateCommand',\n 'mark:delete': 'MarkDeleteCommand',\n 'mark:update-body': 'MarkUpdateBodyCommand',\n 'mark:archive': 'MarkArchiveCommand',\n 'mark:unarchive': 'MarkUnarchiveCommand',\n 'mark:update-entity-types': 'MarkUpdateEntityTypesCommand',\n 'frame:add-entity-type': 'FrameAddEntityTypeCommand',\n 'frame:add-tag-schema': 'FrameAddTagSchemaCommand',\n 'mark:create-ok': 'MarkCreateOk',\n 'mark:create-failed': 'CommandError',\n 'mark:delete-ok': 'MarkDeleteOk',\n 'mark:delete-failed': 'CommandError',\n 'mark:archive-ok': null,\n 'mark:archive-failed': 'CommandError',\n 'mark:unarchive-ok': null,\n 'mark:unarchive-failed': 'CommandError',\n 'mark:update-entity-types-ok': null,\n 'mark:update-entity-types-failed': 'CommandError',\n 'mark:body-update-failed': 'CommandError',\n 'frame:entity-type-add-ok': null,\n 'frame:entity-type-add-failed': 'CommandError',\n 'frame:tag-schema-add-ok': null,\n 'frame:tag-schema-add-failed': 'CommandError',\n 'mark:select-comment': 'SelectionData',\n 'mark:select-tag': 'SelectionData',\n 'mark:select-assessment': 'SelectionData',\n 'mark:select-reference': 'SelectionData',\n 'mark:requested': 'MarkRequestedEvent',\n 'mark:cancel-pending': null, // void\n 'mark:submit': 'MarkSubmitEvent',\n 'mark:assist-request': 'MarkAssistRequestEvent',\n 'mark:progress-dismiss': null, // void\n 'mark:assist-timeout': null, // { resourceId; motivation } — client-local UI signal\n 'mark:create-error': null, // { resourceId; message } — client-local UI signal\n 'mark:delete-error': null, // { resourceId; message } — client-local UI signal\n 'bind:body-error': null, // { resourceId; message } — client-local UI signal\n\n // ── BIND FLOW ───────────────────────────────────────────────────\n 'bind:initiate': 'BindInitiateCommand',\n 'bind:update-body': 'BindUpdateBodyCommand',\n 'bind:body-updated': 'BindBodyUpdated',\n 'bind:body-update-failed': 'CommandError',\n\n // ── MATCH FLOW ──────────────────────────────────────────────────\n 'match:search-requested': 'MatchSearchRequest',\n 'match:search-results': 'MatchSearchResult',\n 'match:search-failed': 'MatchSearchFailed',\n\n // ── GATHER FLOW ─────────────────────────────────────────────────\n 'gather:requested': 'GatherAnnotationRequest',\n 'gather:complete': 'GatherAnnotationComplete',\n 'gather:failed': null, // { correlationId; annotationId } & CommandError\n 'gather:resource-requested': 'GatherResourceRequest',\n 'gather:resource-complete': 'GatherResourceComplete',\n 'gather:resource-failed': null, // { correlationId; resourceId } & CommandError\n 'gather:summary-requested': 'GatherSummaryRequest',\n 'gather:summary-result': null, // { correlationId; response: Record<string, unknown> }\n 'gather:summary-failed': null, // { correlationId } & CommandError\n 'gather:annotation-progress': 'GatherProgress',\n\n // ── BROWSE FLOW ─────────────────────────────────────────────────\n 'browse:resource-requested': 'BrowseResourceRequest',\n 'browse:resource-result': 'BrowseResourceResult',\n 'browse:resource-failed': null, // { correlationId } & CommandError\n 'browse:anchored-text-requested': 'BrowseAnchoredTextRequest',\n 'browse:anchored-text-result': 'BrowseAnchoredTextResult',\n 'browse:anchored-text-failed': null, // { correlationId } & CommandError\n 'browse:resources-requested': 'BrowseResourcesRequest',\n 'browse:resources-result': 'BrowseResourcesResult',\n 'browse:resources-failed': null,\n 'browse:annotations-requested': 'BrowseAnnotationsRequest',\n 'browse:annotations-result': 'BrowseAnnotationsResult',\n 'browse:annotations-failed': null,\n 'browse:annotation-requested': 'BrowseAnnotationRequest',\n 'browse:annotation-result': 'BrowseAnnotationResult',\n 'browse:annotation-failed': null,\n 'browse:events-requested': 'BrowseEventsRequest',\n 'browse:events-result': 'BrowseEventsResult',\n 'browse:events-failed': null,\n 'browse:annotation-history-requested': 'BrowseAnnotationHistoryRequest',\n 'browse:annotation-history-result': 'BrowseAnnotationHistoryResult',\n 'browse:annotation-history-failed': null,\n 'browse:annotation-context-requested': 'BrowseAnnotationContextRequest',\n 'browse:annotation-context-result': null, // { correlationId; response: Record<string, unknown> }\n 'browse:annotation-context-failed': null,\n 'browse:referenced-by-requested': 'BrowseReferencedByRequest',\n 'browse:referenced-by-result': 'BrowseReferencedByResult',\n 'browse:referenced-by-failed': null,\n 'browse:entity-types-requested': 'BrowseEntityTypesRequest',\n 'browse:entity-types-result': 'BrowseEntityTypesResult',\n 'browse:entity-types-failed': null,\n 'browse:tag-schemas-requested': 'BrowseTagSchemasRequest',\n 'browse:tag-schemas-result': 'BrowseTagSchemasResult',\n 'browse:tag-schemas-failed': null,\n 'browse:agents-requested': 'BrowseAgentsRequest',\n 'browse:agents-result': 'BrowseAgentsResult',\n 'browse:agents-failed': null,\n 'browse:directory-requested': 'BrowseDirectoryRequest',\n 'browse:directory-result': 'BrowseDirectoryResult',\n 'browse:directory-failed': null, // { correlationId; path } & CommandError\n 'browse:click': null, // includes runtime `anchorRect?: AnchorRect`\n 'browse:reference-navigate': 'BrowseReferenceNavigateEvent',\n 'browse:entity-type-clicked': 'BrowseEntityTypeClickedEvent',\n\n // ── SHELL (app-scoped UI events, fire on SemiontBrowser bus) ────\n 'panel:toggle': 'BrowsePanelToggleEvent',\n 'panel:open': null, // includes runtime `anchorRect?: AnchorRect`\n 'panel:close': null, // void\n 'shell:sidebar-toggle': null, // void\n 'tabs:close': 'BrowseResourceCloseEvent',\n 'tabs:reorder': 'BrowseResourceReorderEvent',\n 'nav:link-clicked': 'BrowseLinkClickedEvent',\n 'nav:push': 'BrowseRouterPushEvent',\n 'nav:external': null, // includes runtime `cancelFallback: () => void`\n\n // ── BECKON FLOW ─────────────────────────────────────────────────\n 'beckon:hover': 'BeckonHoverEvent',\n 'beckon:focus': 'BeckonFocusEvent',\n 'beckon:sparkle': 'BeckonSparkleEvent',\n\n // ── JOB FLOW ────────────────────────────────────────────────────\n 'job:started': null, // StoredEvent\n 'job:progress': null,\n 'job:completed': null,\n 'job:failed': null,\n 'job:start': 'JobStartCommand',\n 'job:report-progress': 'JobReportProgressCommand',\n 'job:complete': 'JobCompleteCommand',\n 'job:fail': 'JobFailCommand',\n 'job:queued': 'JobQueuedEvent',\n 'job:cancel-requested': 'JobCancelRequest',\n 'job:status-requested': 'JobStatusRequest',\n 'job:create': 'JobCreateCommand',\n 'job:claim': 'JobClaimCommand',\n 'job:status-result': 'JobStatusResult',\n 'job:status-failed': null, // { correlationId } & CommandError\n 'job:created': 'JobCreatedResult',\n 'job:create-failed': null,\n 'job:claimed': null, // { correlationId; response: Record<string, unknown> }\n 'job:claim-failed': null,\n 'job:cancel-ok': null,\n 'job:cancel-failed': 'CommandError',\n\n // ── SETTINGS (frontend-only) ────────────────────────────────────\n 'settings:theme-changed': 'SettingsThemeChangedEvent',\n 'settings:line-numbers-toggled': null, // void\n 'settings:locale-changed': 'SettingsLocaleChangedEvent',\n 'settings:hover-delay-changed': 'SettingsHoverDelayChangedEvent',\n\n // ── WEAVE FLOW ──────────────────────────────────────────────────\n 'weave:applied': null, // { resourceId; sequenceNumber }\n 'smelt:settled': null, // { resourceId; contentChecksum; outcome; reason? }\n 'weave:rebuild': 'WeaveRebuildCommand',\n 'weave:rebuild-ok': null, // { correlationId }\n 'weave:rebuild-failed': null, // { correlationId; message }\n 'smelt:rebuild-anchors': 'SmeltRebuildAnchorsCommand',\n 'smelt:rebuild-anchors-ok': null, // { correlationId }\n 'smelt:rebuild-anchors-failed': null, // { correlationId; message }\n\n // ── SSE infrastructure ──────────────────────────────────────────\n 'stream-connected': null, // Record<string, never>\n 'replay-window-exceeded': null, // inline payload\n 'bus:resume-gap': null, // inline payload\n} as const satisfies Record<EventName, keyof components['schemas'] | null>;\n\n/** Channels where `/bus/emit` validates the payload (non-null schema). */\nexport type EmittableChannel = {\n [K in EventName]: typeof CHANNEL_SCHEMAS[K] extends null ? never : K\n}[EventName];\n","/**\n * Event Type Guards and Extraction Utilities\n *\n * Domain logic for working with resource events.\n * No React dependencies - safe to use in any JavaScript environment.\n */\n\nimport type { StoredEvent } from './event-base';\nimport type { AnnotationUri } from './branded-types';\n\n/**\n * Minimal event shape accepted by event utility functions.\n * Compatible with both the internal `StoredEvent` type and the OpenAPI-derived\n * schema type (`GetEventsResponse['events'][number]`), which lacks `version`.\n *\n * Flat shape — event fields and metadata are peers (no `event` wrapper).\n */\nexport interface StoredEventLike {\n id: string;\n type: string; // Intentionally loose — accepts OpenAPI-derived types where type is string\n timestamp: string;\n userId: string;\n resourceId?: string;\n payload?: unknown;\n metadata: {\n sequenceNumber: number;\n };\n}\n\n// =============================================================================\n// EVENT TYPE GUARDS AND EXTRACTION\n// =============================================================================\n\n/**\n * Extract annotation ID from event payload\n * Returns null if event is not annotation-related\n *\n * For mark:added: extracts full URI from payload.annotation.id\n * For mark:removed/mark:body-updated: constructs full URI from payload.annotationId (UUID) + resourceId\n */\nexport function getAnnotationUriFromEvent(event: StoredEventLike): AnnotationUri | null {\n const payload = event.payload as Record<string, any> | undefined;\n\n if (event.type === 'mark:added') {\n return payload?.annotation?.id as AnnotationUri || null;\n }\n\n if (event.type === 'mark:removed' || event.type === 'mark:body-updated') {\n if (payload?.annotationId && event.resourceId) {\n try {\n const resourceUri = event.resourceId;\n const baseUrl = resourceUri.substring(0, resourceUri.lastIndexOf('/resources/'));\n return `${baseUrl}/annotations/${payload.annotationId}` as AnnotationUri;\n } catch (e) {\n return null;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Check if an event is related to a specific annotation\n */\nexport function isEventRelatedToAnnotation(event: StoredEventLike, annotationUri: AnnotationUri): boolean {\n const eventAnnotationUri = getAnnotationUriFromEvent(event);\n return eventAnnotationUri === annotationUri;\n}\n\n/**\n * Type guard to check if an object is a StoredEvent (flat shape)\n */\nexport function isStoredEvent(event: any): event is StoredEvent {\n return event &&\n typeof event.id === 'string' &&\n typeof event.timestamp === 'string' &&\n typeof event.type === 'string' &&\n typeof event.metadata === 'object' &&\n typeof event.metadata.sequenceNumber === 'number';\n}\n\n","/**\n * Adaptive burst buffer RxJS operator.\n *\n * Passes the first event through immediately (zero latency for interactive use).\n * If more events arrive within the burst window, switches to accumulate mode\n * and flushes batches. Returns to passthrough mode after an idle period.\n *\n * Emits individual items (T) in passthrough mode and arrays (T[]) in batch mode.\n * Consumers distinguish via Array.isArray().\n *\n * Threshold tuning:\n * burstWindowMs — How long to wait for more events before flushing a batch.\n * 50ms is a good default: longer than event-loop jitter (~1-5ms)\n * but short enough to feel responsive.\n * maxBatchSize — Force-flush at this size to bound memory. 500 is safe for\n * Neo4j UNWIND queries. Increase if graph writes are cheap.\n * idleTimeoutMs — How long after the last flush before returning to passthrough.\n * 200ms is a good default. Must be >= burstWindowMs.\n *\n * See: packages/graph/docs/ARCHITECTURE.md for Weaver context.\n */\n\nimport { Observable, OperatorFunction } from 'rxjs';\n\nexport interface BurstBufferOptions {\n /**\n * Time window (ms) to detect burst activity after an event.\n * If another event arrives within this window, it is buffered.\n * The buffer flushes when no new event arrives for this duration (debounce).\n *\n * Recommended: 50ms.\n */\n burstWindowMs: number;\n\n /**\n * Maximum events to accumulate before forcing a flush.\n * Prevents unbounded memory growth during sustained bursts.\n *\n * Recommended: 500.\n */\n maxBatchSize: number;\n\n /**\n * Time (ms) of silence after the last flush before returning to passthrough mode.\n * The next event after this timeout emits immediately (leading edge).\n * Must be >= burstWindowMs.\n *\n * Recommended: 200ms.\n */\n idleTimeoutMs: number;\n}\n\n/**\n * Adaptive burst buffer operator.\n *\n * State machine:\n * PASSTHROUGH → event arrives → emit immediately, transition to ACCUMULATING\n * ACCUMULATING → event arrives → buffer it, reset burst timer\n * ACCUMULATING → burst timer fires (no new events for burstWindowMs) → flush buffer as T[]\n * ACCUMULATING → buffer reaches maxBatchSize → flush buffer as T[]\n * After flush → idle timer starts\n * Idle timer fires (no new events for idleTimeoutMs) → transition to PASSTHROUGH\n */\nexport function burstBuffer<T>(\n options: BurstBufferOptions\n): OperatorFunction<T, T | T[]> {\n const { burstWindowMs, maxBatchSize, idleTimeoutMs } = options;\n\n return (source: Observable<T>) =>\n new Observable<T | T[]>((subscriber) => {\n let mode: 'passthrough' | 'accumulating' = 'passthrough';\n let buffer: T[] = [];\n let burstTimer: ReturnType<typeof setTimeout> | null = null;\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n\n function clearBurstTimer() {\n if (burstTimer !== null) {\n clearTimeout(burstTimer);\n burstTimer = null;\n }\n }\n\n function clearIdleTimer() {\n if (idleTimer !== null) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n }\n\n function flush() {\n if (buffer.length === 0) return;\n const batch = buffer;\n buffer = [];\n subscriber.next(batch);\n }\n\n function startIdleTimer() {\n clearIdleTimer();\n idleTimer = setTimeout(() => {\n idleTimer = null;\n mode = 'passthrough';\n }, idleTimeoutMs);\n }\n\n const subscription = source.subscribe({\n next(value: T) {\n clearIdleTimer();\n\n if (mode === 'passthrough') {\n // Leading edge: emit immediately\n subscriber.next(value);\n // Transition to accumulating — next event within burstWindowMs gets buffered\n mode = 'accumulating';\n // Start a burst timer: if nothing else arrives, start idle countdown\n burstTimer = setTimeout(() => {\n burstTimer = null;\n flush(); // flush anything accumulated (normally empty at this point)\n startIdleTimer();\n }, burstWindowMs);\n return;\n }\n\n // mode === 'accumulating'\n buffer.push(value);\n\n // Reset the burst window timer (debounce pattern)\n clearBurstTimer();\n\n if (buffer.length >= maxBatchSize) {\n // Force flush at max batch size\n flush();\n startIdleTimer();\n } else {\n // Debounce: flush after burstWindowMs of silence\n burstTimer = setTimeout(() => {\n burstTimer = null;\n flush();\n startIdleTimer();\n }, burstWindowMs);\n }\n },\n\n error(err) {\n clearBurstTimer();\n clearIdleTimer();\n flush();\n subscriber.error(err);\n },\n\n complete() {\n clearBurstTimer();\n clearIdleTimer();\n flush();\n subscriber.complete();\n },\n });\n\n // Teardown: clean up timers and unsubscribe from source\n return () => {\n clearBurstTimer();\n clearIdleTimer();\n subscription.unsubscribe();\n };\n });\n}\n","/**\n * serializePerKey — run async work serialized per key, parallel across keys.\n *\n * Invariant: two calls with the same `key` run strictly in sequence (the\n * second `work` does not start until the first has settled). Calls with\n * different keys overlap freely.\n *\n * Error isolation: a rejected work function does not poison subsequent\n * tasks for the same key. The next task starts fresh from whatever state\n * the failed task left behind. The rejection still propagates to *this*\n * caller.\n *\n * Registry cleanup: the entry for a key is removed as soon as its chain\n * empties, so the Map stays bounded by the number of keys with work\n * currently in flight, not by the total number of keys ever seen.\n *\n * ## Usage\n *\n * ```ts\n * const chains = new Map<string, Promise<void>>();\n *\n * async function write(resourceId: string, event: Event) {\n * return serializePerKey(resourceId, chains, async () => {\n * // Read-modify-write on a view file. Any two concurrent calls with\n * // the same resourceId will be serialized; different resourceIds\n * // will proceed in parallel.\n * const view = await viewStorage.get(resourceId);\n * applyEvent(view, event);\n * await viewStorage.save(resourceId, view);\n * });\n * }\n * ```\n *\n * ## When to use this vs RxJS `groupBy + concatMap`\n *\n * Use `serializePerKey` when the work arrives as **direct method calls**\n * that need to block the caller until completion. This is the RPC shape\n * — think `EventStore.appendEvent` calling `await views.materializeResource(...)`\n * and needing the view written before any subscriber sees the published\n * event.\n *\n * Use RxJS `groupBy(keyFn) + concatMap(...)` when the work arrives as an\n * **event stream** that a component subscribes to once at startup. This\n * is how `Smelter`, `Weaver`, and `Gatherer` serialize their own\n * per-resource work — see their implementations in `packages/make-meaning`.\n *\n * Both patterns solve the same logical problem (\"serialize work per key\").\n * The choice is dictated by whether the caller is awaiting the result.\n */\nexport async function serializePerKey<K, T>(\n key: K,\n chains: Map<K, Promise<void>>,\n work: () => Promise<T>,\n): Promise<T> {\n const prev = chains.get(key) ?? Promise.resolve();\n\n // Chain onto prev, swallowing any error from the previous link so one\n // bad task doesn't poison subsequent ones for the same key. The new\n // link's own errors still propagate to our caller via `await next`.\n let result: T;\n const next = prev\n .catch(() => { /* prior failure doesn't block us */ })\n .then(async () => {\n result = await work();\n });\n\n chains.set(key, next);\n\n try {\n await next;\n return result!;\n } finally {\n // Only clear the entry if we're still the tail. If another caller\n // has already chained onto us, leave it so the chain stays intact.\n if (chains.get(key) === next) {\n chains.delete(key);\n }\n }\n}\n","/**\n * Logger interface for observability\n *\n * This interface is intentionally framework-agnostic to work with any logger\n * (winston, pino, bunyan, or simple console).\n *\n * Example usage:\n * ```typescript\n * import winston from 'winston';\n *\n * const logger = winston.createLogger({\n * level: 'debug',\n * transports: [new winston.transports.Console()]\n * });\n *\n * const service = new MyService(logger);\n * ```\n */\nexport interface Logger {\n debug(message: string, meta?: any): void;\n info(message: string, meta?: any): void;\n warn(message: string, meta?: any): void;\n error(message: string, meta?: any): void;\n child(meta: Record<string, any>): Logger;\n}\n\n/**\n * Serialize an error value into a form that JSON.stringify can handle\n * meaningfully.\n *\n * Winston's default JSON formatter serializes `Error` instances as `{}`\n * because `message`, `stack`, and `name` are non-enumerable properties on\n * the Error prototype. That means `logger.error('x', { error })` with a\n * raw Error argument produces useless log lines like\n * `{\"error\":{},\"message\":\"x\",...}`, throwing away the information you\n * actually need to diagnose the failure.\n *\n * This helper extracts the parts you want to see in a log — name,\n * message, stack, and cause — and leaves non-Error values alone (so\n * strings, numbers, and plain objects pass through unchanged).\n *\n * ## Usage\n *\n * ```ts\n * try {\n * await doSomething();\n * } catch (error) {\n * logger.error('Something failed', { error: errField(error) });\n * }\n * ```\n *\n * Use this at every `logger.error` call site that includes an `error`\n * field derived from a catch block. Raw `{ error }` without this helper\n * is almost always a bug.\n */\nexport function errField(error: unknown): unknown {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n ...(error.cause !== undefined && { cause: errField(error.cause) }),\n };\n }\n return error;\n}\n","/**\n * Annotation body utilities\n *\n * These are the matcher primitives used by the `mark:body-updated` event\n * replay path (ViewMaterializer and Weaver) to apply add/remove/\n * replace operations against an annotation body.\n */\n\nimport type { components } from './types';\nimport type { Annotation } from './annotation-types';\n\ntype BodyPurpose = components['schemas']['BodyPurpose'];\n\n/**\n * Identity of a body item for matching purposes.\n *\n * Identity is `type + source` for SpecificResource and `type + value` for\n * TextualBody. `purpose` is OPTIONAL: if the caller provides it, it's\n * included in the match (used to disambiguate same-source bodies under\n * different purposes, per the W3C Web Annotation model). If the caller\n * omits it, the matcher ignores purpose and matches on identity alone.\n *\n * Callers SHOULD provide `purpose` when they know it (e.g., the bind flow\n * always unlinks a `purpose: 'linking'` body) so that future multi-purpose\n * annotations continue to disambiguate correctly. Leaving `purpose`\n * unspecified matches whichever purpose comes first in the body — which is\n * fine today because Semiont annotations currently have at most one body\n * item per (type, source/value) pair.\n */\nexport type BodyItemIdentity =\n | { type: 'SpecificResource'; source: string; purpose?: BodyPurpose }\n | { type: 'TextualBody'; value: string; purpose?: BodyPurpose };\n\n/**\n * Find a body item by identity. Returns the index of the first match, or -1.\n *\n * See `BodyItemIdentity` for matching semantics.\n */\nexport function findBodyItem(\n body: Annotation['body'],\n identity: BodyItemIdentity,\n): number {\n if (!Array.isArray(body)) {\n return -1;\n }\n\n for (let i = 0; i < body.length; i++) {\n const item = body[i];\n\n if (typeof item !== 'object' || item === null || !('type' in item)) {\n continue;\n }\n\n const itemType = (item as { type: unknown }).type;\n if (itemType !== identity.type) {\n continue;\n }\n\n // Identity field match (source or value)\n if (identity.type === 'SpecificResource') {\n if (!('source' in item)) continue;\n const itemSource = (item as { source: unknown }).source;\n if (itemSource !== identity.source) continue;\n } else {\n if (!('value' in item)) continue;\n const itemValue = (item as { value: unknown }).value;\n if (itemValue !== identity.value) continue;\n }\n\n // Purpose match — ONLY if the caller specified one. Omitted purpose\n // means \"any purpose on this identity\", which is what the bind-flow\n // unlinker wants today.\n if (identity.purpose !== undefined) {\n const itemPurpose = (item as { purpose?: unknown }).purpose;\n if (itemPurpose !== identity.purpose) continue;\n }\n\n return i;\n }\n\n return -1;\n}\n","/**\n * ID generation utilities.\n *\n * Built on `crypto.getRandomValues()`, NOT `crypto.randomUUID()`: browsers\n * expose `randomUUID` only in secure contexts (https, `http://localhost`,\n * `http://127.0.0.1`), so a page served over plain http from any other host\n * has no `randomUUID` and calling it throws — which broke the frontend from\n * the host-gateway IP (.plans/bugs/crypto-randomuuid-insecure-context.md).\n * `getRandomValues` is cryptographically sound and available in ALL contexts,\n * Node and browser, secure or not.\n */\n\n// Declared here because the core package tsconfig uses lib:ES2022 (no dom types).\ndeclare const crypto: { getRandomValues<T extends ArrayBufferView>(array: T): T };\n\nfunction v4Bytes(): Uint8Array {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8]! & 0x3f) | 0x80; // variant 10xx\n return bytes;\n}\n\nfunction hex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Generate a UUID v4 string WITHOUT dashes (32 hex chars).\n *\n * The dashless form is data shape: persisted annotation/resource/job ids are\n * built from it and land in URIs. Do not change the format.\n */\nexport function generateUuid(): string {\n return hex(v4Bytes());\n}\n\n/**\n * Generate a canonical dashed UUID v4 (36 chars, 8-4-4-4-12) — the format\n * `crypto.randomUUID()` produces, without its secure-context requirement.\n *\n * Use for ephemeral wire ids (`correlationId`s and the like).\n */\nexport function uuidV4(): string {\n const h = hex(v4Bytes());\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;\n}\n","/**\n * Annotation Assembly\n *\n * Pure functions for building W3C Annotations and applying body operations.\n * No EventBus, no persistence — just data transformation.\n */\n\nimport type { components } from './types';\nimport type { Selector } from './payload-types';\nimport type { Annotation } from './annotation-types';\nimport { annotationId } from './identifiers';\nimport { generateUuid } from './id-generation';\n\ntype Agent = components['schemas']['Agent'];\ntype AnnotationBody = components['schemas']['AnnotationBody'];\ntype CreateAnnotationRequest = components['schemas']['CreateAnnotationRequest'];\ntype UpdateAnnotationBodyRequest = components['schemas']['UpdateAnnotationBodyRequest'];\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\n\nexport interface AssembledAnnotation {\n annotation: Annotation;\n bodyArray: AnnotationBody[];\n}\n\n// =============================================================================\n// Selector utilities used by assembleAnnotation\n// =============================================================================\n\n/**\n * Get TextPositionSelector from a selector (single or array)\n */\nexport function getTextPositionSelector(selector: Selector | Selector[] | undefined): TextPositionSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextPositionSelector');\n if (!found) return null;\n return found.type === 'TextPositionSelector' ? found : null;\n}\n\n/**\n * Get SvgSelector from a selector (single or array)\n */\nexport function getSvgSelector(selector: Selector | Selector[] | undefined): SvgSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'SvgSelector');\n if (!found) return null;\n return found.type === 'SvgSelector' ? found : null;\n}\n\n/**\n * Get FragmentSelector from a selector (single or array)\n */\nexport function getFragmentSelector(selector: Selector | Selector[] | undefined): FragmentSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'FragmentSelector');\n if (!found) return null;\n return found.type === 'FragmentSelector' ? found : null;\n}\n\n/**\n * Validate SVG markup for W3C compliance\n *\n * @returns null if valid, error message if invalid\n */\nexport function validateSvgMarkup(svg: string): string | null {\n if (!svg.includes('xmlns=\"http://www.w3.org/2000/svg\"')) {\n return 'SVG must include xmlns=\"http://www.w3.org/2000/svg\" attribute';\n }\n\n if (!svg.includes('<svg') || !svg.includes('</svg>')) {\n return 'SVG must have opening and closing tags';\n }\n\n const shapeElements = ['rect', 'circle', 'ellipse', 'polygon', 'polyline', 'path', 'line'];\n const hasShape = shapeElements.some(shape =>\n svg.includes(`<${shape}`) || svg.includes(`<${shape} `)\n );\n\n if (!hasShape) {\n return 'SVG must contain at least one shape element (rect, circle, ellipse, polygon, polyline, path, or line)';\n }\n\n return null;\n}\n\n// =============================================================================\n// Annotation assembly\n// =============================================================================\n\n/**\n * Build a complete W3C Annotation from a CreateAnnotationRequest.\n *\n * Generates a bare annotation ID (no URL prefix). URIs are constructed\n * at the API boundary when returning responses to clients.\n *\n * Throws on invalid input (missing motivation, invalid SVG markup). The target\n * selector is OPTIONAL — a source-only target annotates the whole resource (W3C;\n * e.g. resource-level edges), per RESOURCE-LEVEL-ANCHOR.\n */\nexport function assembleAnnotation(\n request: CreateAnnotationRequest,\n creator: Agent,\n): AssembledAnnotation {\n const newAnnotationId = annotationId(generateUuid());\n\n // The target selector is OPTIONAL — a source-only target annotates the whole\n // resource (W3C; e.g. resource-level edges). When an SvgSelector IS present,\n // its markup must still be valid.\n const svgSelector = getSvgSelector(request.target.selector);\n if (svgSelector) {\n const svgError = validateSvgMarkup(svgSelector.value);\n if (svgError) {\n throw new Error(`Invalid SVG markup: ${svgError}`);\n }\n }\n\n if (!request.motivation) {\n throw new Error('motivation is required');\n }\n\n const now = new Date().toISOString();\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld' as const,\n 'type': 'Annotation' as const,\n id: newAnnotationId,\n motivation: request.motivation,\n target: request.target,\n body: request.body as Annotation['body'],\n creator,\n created: now,\n modified: now,\n };\n\n const bodyArray = (Array.isArray(request.body) ? request.body : request.body ? [request.body] : []) as AnnotationBody[];\n\n return { annotation, bodyArray };\n}\n\n/**\n * Apply body operations (add/remove/replace) to an annotation's body array.\n * Returns a new array — does not mutate the input.\n */\nexport function applyBodyOperations(\n body: Annotation['body'],\n operations: UpdateAnnotationBodyRequest['operations'],\n): AnnotationBody[] {\n const bodyArray = Array.isArray(body) ? [...body] : [];\n\n for (const op of operations) {\n if (op.op === 'add') {\n const exists = bodyArray.some(item =>\n JSON.stringify(item) === JSON.stringify(op.item)\n );\n if (!exists) {\n bodyArray.push(op.item);\n }\n } else if (op.op === 'remove') {\n const index = bodyArray.findIndex(item =>\n JSON.stringify(item) === JSON.stringify(op.item)\n );\n if (index !== -1) {\n bodyArray.splice(index, 1);\n }\n } else if (op.op === 'replace') {\n const index = bodyArray.findIndex(item =>\n JSON.stringify(item) === JSON.stringify(op.oldItem)\n );\n if (index !== -1) {\n bodyArray[index] = op.newItem;\n }\n }\n }\n\n return bodyArray;\n}\n","/**\n * Annotation and Selector Utilities\n *\n * Pure TypeScript utilities for working with W3C Web Annotations.\n * No React dependencies - safe to use in any JavaScript environment.\n *\n * Body is either empty array (stub) or single SpecificResource (resolved)\n * Body can be array of TextualBody (tagging) + SpecificResource (linking)\n * Target can be simple string IRI or object with source and optional selector\n */\n\nimport type { components } from './types';\nimport type { Selector } from './payload-types';\nimport type { Annotation } from './annotation-types';\n\n// Re-export selector utilities (canonical location is annotation-assembly)\nexport {\n getTextPositionSelector,\n getSvgSelector,\n getFragmentSelector,\n validateSvgMarkup,\n} from './annotation-assembly';\ntype HighlightAnnotation = Annotation;\ntype ReferenceAnnotation = Annotation;\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype TextQuoteSelector = components['schemas']['TextQuoteSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\n\n// Re-export selector types for convenience\nexport type { TextPositionSelector, TextQuoteSelector, SvgSelector, FragmentSelector, Selector };\n\n/**\n * Get the source from an annotation body (null if stub)\n * Search for SpecificResource in body array\n */\nexport function getBodySource(body: Annotation['body']): string | null {\n if (Array.isArray(body)) {\n // Search for SpecificResource with source\n for (const item of body) {\n if (\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n 'source' in item\n ) {\n const itemType = (item as { type: unknown }).type;\n const itemSource = (item as { source: unknown }).source;\n\n if (itemType === 'SpecificResource' && typeof itemSource === 'string') {\n return itemSource;\n }\n }\n }\n return null; // No SpecificResource found = stub\n }\n\n // Single body object (SpecificResource)\n if (\n typeof body === 'object' &&\n body !== null &&\n 'type' in body &&\n 'source' in body\n ) {\n const bodyType = (body as { type: unknown }).type;\n const bodySource = (body as { source: unknown }).source;\n\n if (bodyType === 'SpecificResource' && typeof bodySource === 'string') {\n return bodySource;\n }\n }\n\n return null;\n}\n\n/**\n * Get the type from an annotation body (returns first body type in array)\n */\nexport function getBodyType(body: Annotation['body']): 'TextualBody' | 'SpecificResource' | null {\n if (Array.isArray(body)) {\n if (body.length === 0) {\n return null;\n }\n // Return type of first body item\n if (typeof body[0] === 'object' && body[0] !== null && 'type' in body[0]) {\n const firstType = (body[0] as { type: unknown }).type;\n if (firstType === 'TextualBody' || firstType === 'SpecificResource') {\n return firstType;\n }\n }\n return null;\n }\n\n // Single body object\n if (typeof body === 'object' && body !== null && 'type' in body) {\n const bodyType = (body as { type: unknown }).type;\n if (bodyType === 'TextualBody' || bodyType === 'SpecificResource') {\n return bodyType;\n }\n }\n\n return null;\n}\n\n/**\n * Check if body is resolved (has a source)\n * Check for SpecificResource in body array\n */\nexport function isBodyResolved(body: Annotation['body']): boolean {\n return getBodySource(body) !== null;\n}\n\n/**\n * Get the source IRI from target (handles both string and object forms)\n */\nexport function getTargetSource(target: Annotation['target']): string {\n if (typeof target === 'string') {\n return target;\n }\n return target.source;\n}\n\n/**\n * Get the selector from target (undefined if string or no selector)\n */\nexport function getTargetSelector(target: Annotation['target']) {\n if (typeof target === 'string') {\n return undefined;\n }\n return target.selector;\n}\n\n/**\n * Check if target has a selector\n */\nexport function hasTargetSelector(target: Annotation['target']): boolean {\n return typeof target !== 'string' && target.selector !== undefined;\n}\n\n/**\n * Type guard to check if an annotation is a highlight\n */\nexport function isHighlight(annotation: Annotation): annotation is HighlightAnnotation {\n return annotation.motivation === 'highlighting';\n}\n\n/**\n * Type guard to check if an annotation is a reference (linking)\n */\nexport function isReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return annotation.motivation === 'linking';\n}\n\n/**\n * Type guard to check if an annotation is an assessment\n */\nexport function isAssessment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'assessing';\n}\n\n/**\n * Type guard to check if an annotation is a comment\n */\nexport function isComment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'commenting';\n}\n\n/**\n * Type guard to check if an annotation is a tag\n */\nexport function isTag(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'tagging';\n}\n\n/**\n * Extract comment text from a comment annotation's body\n * @param annotation - The annotation to extract comment text from\n * @returns The comment text, or undefined if not a comment or no text found\n */\nexport function getCommentText(annotation: Annotation): string | undefined {\n if (!isComment(annotation)) return undefined;\n const body = Array.isArray(annotation.body) ? annotation.body[0] : annotation.body;\n if (body && 'value' in body) {\n return body.value;\n }\n return undefined;\n}\n\n/**\n * Type guard to check if a reference annotation is a stub (unresolved)\n * Stub if no SpecificResource in body array\n */\nexport function isStubReference(annotation: Annotation): boolean {\n return isReference(annotation) && !isBodyResolved(annotation.body);\n}\n\n/**\n * Type guard to check if a reference annotation is resolved\n * Resolved if SpecificResource exists in body array\n */\nexport function isResolvedReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return isReference(annotation) && isBodyResolved(annotation.body);\n}\n\n// =============================================================================\n// SELECTOR UTILITIES\n// =============================================================================\n\n/**\n * Get the exact text from a selector (single or array)\n *\n * When selector is an array, tries to find a TextQuoteSelector (which has exact text).\n * TextPositionSelector does not have exact text, only character offsets.\n * Handles undefined selector (when target is a string IRI with no selector)\n */\nexport function getExactText(selector: Selector | Selector[] | undefined): string {\n if (!selector) {\n return ''; // No selector means entire resource\n }\n const selectors = Array.isArray(selector) ? selector : [selector];\n\n // Try to find TextQuoteSelector (has exact text)\n const quoteSelector = selectors.find(s => s.type === 'TextQuoteSelector') as TextQuoteSelector | undefined;\n if (quoteSelector) {\n return quoteSelector.exact;\n }\n\n // No TextQuoteSelector found\n return '';\n}\n\n/**\n * Get the exact text from an annotation's target selector\n * Uses getTargetSelector helper to safely get selector\n */\nexport function getAnnotationExactText(annotation: Annotation): string {\n const selector = getTargetSelector(annotation.target);\n return getExactText(selector as Selector | Selector[] | undefined);\n}\n\n/**\n * Get the primary selector from a selector (single or array)\n *\n * When selector is an array, returns the first selector.\n * When selector is a single object, returns it as-is.\n */\nexport function getPrimarySelector(selector: Selector | Selector[]): Selector {\n if (Array.isArray(selector)) {\n if (selector.length === 0) {\n throw new Error('Empty selector array');\n }\n const first = selector[0];\n if (!first) {\n throw new Error('Invalid selector array');\n }\n return first;\n }\n return selector;\n}\n\n/**\n * Get TextQuoteSelector from a selector (single or array)\n *\n * Returns the first TextQuoteSelector found, or null if none exists.\n */\nexport function getTextQuoteSelector(selector: Selector | Selector[]): TextQuoteSelector | null {\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextQuoteSelector');\n if (!found) return null;\n return found.type === 'TextQuoteSelector' ? found : null;\n}\n\n/**\n * Extract bounding box from SVG markup\n *\n * Attempts to extract x, y, width, height from the SVG viewBox or root element.\n * Returns null if bounding box cannot be determined.\n */\nexport function extractBoundingBox(svg: string): { x: number; y: number; width: number; height: number } | null {\n // Try to extract viewBox attribute from SVG element\n const viewBoxMatch = svg.match(/<svg[^>]*viewBox=\"([^\"]+)\"/);\n if (viewBoxMatch) {\n const values = viewBoxMatch[1].split(/\\s+/).map(parseFloat);\n if (values.length === 4 && values.every(v => !isNaN(v))) {\n return {\n x: values[0],\n y: values[1],\n width: values[2],\n height: values[3]\n };\n }\n }\n\n // Try to extract width/height attributes from SVG element (assume x=0, y=0)\n const svgTagMatch = svg.match(/<svg[^>]*>/);\n if (svgTagMatch) {\n const svgTag = svgTagMatch[0];\n const widthMatch = svgTag.match(/width=\"([^\"]+)\"/);\n const heightMatch = svgTag.match(/height=\"([^\"]+)\"/);\n\n if (widthMatch && heightMatch) {\n const width = parseFloat(widthMatch[1]);\n const height = parseFloat(heightMatch[1]);\n\n if (!isNaN(width) && !isNaN(height)) {\n return { x: 0, y: 0, width, height };\n }\n }\n }\n\n return null;\n}\n","/**\n * PDF viewrect FragmentSelector codec.\n *\n * `PdfCoordinate` is a bounding rectangle in PDF point space: origin at the\n * bottom-left of the page, Y increasing upward. The Y-flip to canvas pixels\n * lives in the browser (`react-ui`); the server has no canvas.\n *\n * These functions are the viewrect peer of the W3C `FragmentSelector` wrapper in\n * `web-annotation-utils`: they serialize/parse the RFC 3778\n * `page=N&viewrect=left,top,width,height` value. `@semiont/content` (geometry\n * from the text layer), `@semiont/jobs` (serialization at write time), and the\n * browser canvas all import them from here — no package reaches into the UI.\n *\n * RFC 3778 PDF Fragment Identifiers: https://tools.ietf.org/html/rfc3778\n */\n\n/**\n * A bounding rectangle in PDF point coordinates.\n * Origin at the bottom-left of the page; Y increases upward.\n */\nexport interface PdfCoordinate {\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Serialize a PdfCoordinate to an RFC 3778 FragmentSelector value.\n * Format: `page=N&viewrect=left,top,width,height` (all in PDF points).\n */\nexport function createFragmentSelector(coord: PdfCoordinate): string {\n return `page=${coord.page}&viewrect=${coord.x},${coord.y},${coord.width},${coord.height}`;\n}\n\n/**\n * Parse an RFC 3778 FragmentSelector value into PDF coordinates.\n * Returns null when the value is not a well-formed page + viewrect fragment.\n */\nexport function parseFragmentSelector(fragment: string): PdfCoordinate | null {\n const pageMatch = fragment.match(/page=(\\d+)/);\n if (!pageMatch) return null;\n\n // Each coordinate: optional sign, integer part, optional fraction — tight enough\n // to round-trip negatives and reject malformed numbers (e.g. \"1.2.3\").\n const viewrectMatch = fragment.match(\n /viewrect=(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?)/\n );\n if (!viewrectMatch) return null;\n\n return {\n page: parseInt(pageMatch[1], 10),\n x: parseFloat(viewrectMatch[1]),\n y: parseFloat(viewrectMatch[2]),\n width: parseFloat(viewrectMatch[3]),\n height: parseFloat(viewrectMatch[4]),\n };\n}\n\n/** Extract the 1-indexed page number from a FragmentSelector value. */\nexport function getPageFromFragment(fragment: string): number | null {\n const match = fragment.match(/page=(\\d+)/);\n return match ? parseInt(match[1], 10) : null;\n}\n","/**\n * Text ↔ geometry anchoring for PDFs.\n *\n * Two directions over the same pairing of text and the runs that index it:\n * `locate` turns a character span into rectangles (an annotation the model\n * produced by quoting text), `textUnder` turns a rectangle into characters (an\n * annotation a person produced by dragging a box). They are inverses and live\n * together deliberately.\n *\n * This is pure arithmetic over plain data, so it sits here beside\n * `PdfCoordinate` and the viewrect codec rather than in `@semiont/content`:\n * the browser canvas needs `textUnder` at drag time and cannot import\n * `@semiont/content`, which carries pdf.js, Tesseract and `node:fs`.\n * *Producing* an `AnchoredText` — from a text layer or from OCR — stays there.\n *\n * Coordinates are PDF points with the origin at the bottom-left of the page,\n * Y increasing upward. The Y-flip to canvas pixels lives in the browser.\n */\n\nimport type { PdfCoordinate } from './pdf-coordinates';\nimport type { components } from './types';\n\n/**\n * A single text item (one text run, roughly a word) from a PDF.\n * Character offsets refer to positions in the paired `AnchoredText.text`.\n */\nexport interface PdfTextItem {\n start: number; // Char offset in `AnchoredText.text` (inclusive)\n end: number; // Char offset in `AnchoredText.text` (exclusive)\n page: number; // 1-indexed page number\n x: number; // X position in PDF points (origin: bottom-left of page)\n y: number; // Y position in PDF points (origin: bottom-left of page)\n width: number;\n height: number;\n}\n\n/**\n * Text paired with the geometry that indexes it — the minimum needed to turn a\n * character range into a Selection, or a rectangle into a quote.\n *\n * This is the contract `locate`, `textUnder` and the annotation builders\n * actually require; they do not need pages, form fields, or anything else a\n * full `PdfTextLayer` carries. Naming it separately lets OCR'd content\n * (recovered from pixels, so not a \"text layer\" in the PDF sense) satisfy the\n * same anchoring path.\n */\nexport interface AnchoredText {\n text: string;\n items: PdfTextItem[];\n}\n\n/**\n * The full outcome of text extraction for one representation — the record\n * the anchored-text store holds and the wire serves (PERSIST-ANCHORS\n * decision D1): an `AnchoredText` plus its provenance (`method`, `pdfClass`,\n * `ocrConfidence`, `unreadPages`), or a named decline. `AnchoredText` stays\n * the anchoring vocabulary; this is the stored/served record. Aliased from\n * the generated spec type so the wire shape has exactly one authority.\n */\nexport type ExtractionOutcome = components['schemas']['ExtractionOutcome'];\n\n/**\n * One text run as pdf.js reports it, narrowed to the fields anchoring reads.\n * Structural on purpose: core takes no dependency on pdfjs-dist, so each\n * producer filters marked-content items at its own boundary and passes the\n * text runs through.\n */\nexport interface PdfTextRun {\n str: string;\n /** pdf.js text matrix `[a, b, c, d, x, y]`; only x/y are read. */\n transform: number[];\n width: number;\n height: number;\n hasEOL?: boolean;\n}\n\n/**\n * pdf.js interleaves marked-content items with text runs in `getTextContent()`;\n * only the latter carry `str`. Both producers filter with this before calling\n * `anchorRuns`, so the boundary rule is stated once.\n */\nexport function isTextRun<T>(item: T): item is T & PdfTextRun {\n return typeof item === 'object' && item !== null && 'str' in item;\n}\n\n/**\n * Turns one page's pdf.js text runs into `AnchoredText`.\n *\n * This is the offset and separator convention — what `text` says, and where\n * each item points into it. Both producers share it: the server extractor\n * reading a whole document, and the browser canvas reading the page under a\n * drag. Divergence would mean the same rectangle quoting differently depending\n * on which side captured it.\n *\n * Offsets are page-local. A caller assembling a multi-page document shifts them\n * by the length of the text already accumulated.\n */\nexport function anchorRuns(runs: PdfTextRun[], page: number): AnchoredText {\n const items: PdfTextItem[] = [];\n let text = '';\n\n for (const run of runs) {\n if (run.str.trim()) {\n const start = text.length;\n text += run.str;\n const end = text.length; // range covers only this run's own chars\n\n const [, , , , x, y] = run.transform;\n items.push({ start, end, page, x, y, width: run.width, height: run.height });\n\n // Separator AFTER recording the run, so its [start, end) never\n // includes it. pdf.js flags the last run on a line with hasEOL —\n // newline there, space between words otherwise, so reading-order\n // lines don't glue (e.g. \"textsecond\").\n text += run.hasEOL ? '\\n' : ' ';\n } else if (run.hasEOL) {\n // Standalone end-of-line marker (empty/whitespace str): keep the\n // line break without letting whitespace-only runs add stray spaces.\n text += '\\n';\n }\n }\n\n return { text, items };\n}\n\n/**\n * Items whose baseline Y is within this many PDF points are treated as being on\n * the same line. Tuned for ~12pt body text; revisit for documents with large or\n * variable font sizes (Phase 4 / #738).\n */\nconst SAME_LINE_THRESHOLD_PT = 2;\n\n/**\n * Locates bounding rectangles for a span of text in an AnchoredText\n * (single-line or multi-line).\n *\n * Finds all overlapping items [start, end), groups them by page and line, and\n * records one bounding rectangle per line as a PdfCoordinate.\n *\n * Returns both the per-line `rects` and the `overlap` items they were computed\n * from — so a caller that also needs the covered text (e.g. buildPdfAnnotation's\n * geometry↔text containment invariant) reuses this single `items` scan\n * instead of re-filtering. Both arrays are empty if no item overlaps the span.\n */\nexport function locate(\n anchored: AnchoredText,\n start: number,\n end: number\n): { rects: PdfCoordinate[]; overlap: PdfTextItem[] } {\n const overlap: PdfTextItem[] = anchored.items.filter(\n item => item.start < end && item.end > start\n );\n if (overlap.length === 0) return { rects: [], overlap };\n\n const pages: Map<number, PdfTextItem[]> = groupItemsByPage(overlap);\n const rects: PdfCoordinate[] = [];\n\n // for each page, group items into lines and compute one rectangle per line\n for (const [page, pageItems] of pages) {\n const lines = groupItemsByLine(pageItems, SAME_LINE_THRESHOLD_PT);\n // Compute one bounding rectangle per line and add it to rects.\n // Boundary items that extend past [start, end) are clipped by character\n // fraction (PDF-GENERATION P4): renderers like Typst emit ONE item per\n // line, so without clipping a mid-line phrase would bound the whole\n // line. Proportional interpolation is the measured fallback — exact\n // glyph metrics need the operator-list route (open question 2) and can\n // replace this arithmetic without changing the shape.\n for (const lineItems of lines) {\n const edges = lineItems.map(i => {\n const chars = i.end - i.start;\n const left = i.start < start && chars > 0\n ? i.x + i.width * ((start - i.start) / chars)\n : i.x;\n const right = i.end > end && chars > 0\n ? i.x + i.width * ((end - i.start) / chars)\n : i.x + i.width;\n return { left, right };\n });\n const x = Math.min(...edges.map(e => e.left));\n const right = Math.max(...edges.map(e => e.right));\n const y = Math.min(...lineItems.map(i => i.y));\n const top = Math.max(...lineItems.map(i => i.y + i.height));\n rects.push({page, x, y, width: right - x, height: top - y});\n }\n }\n return { rects, overlap };\n}\n\n/**\n * The inverse of `locate`: given a rectangle, returns the text under it.\n *\n * A hand-drawn PDF rectangle otherwise carries no quoted text at all, so every\n * panel that quotes an annotation shows it blank\n * (.plans/PDF-MANUAL-ANNOTATION-TEXT.md).\n *\n * `rect` is in the same PDF-point, bottom-left-origin space as `PdfTextItem`,\n * so a canvas drag rectangle passes straight in. A run counts as covered when\n * the rectangle overlaps `RUN_COVERAGE_THRESHOLD` of its area — see there for\n * why any-intersection is not survivable for a hand-drawn box.\n *\n * Covered runs are emitted in reading order (`text` offset order), which\n * inherits the extractor's known column-major ordering on multi-column pages\n * rather than answering it a second, different way.\n *\n * Returns `''` when nothing is covered — over an image, over whitespace, or\n * over a scanned page with no text layer. Callers must then emit no\n * `TextQuoteSelector` at all: an empty quote would assert the box was drawn\n * around nothing.\n */\nexport function textUnder(anchored: AnchoredText, rect: PdfCoordinate): string {\n const covered = anchored.items\n .filter(item => item.page === rect.page && covers(item, rect))\n .sort((a, b) => a.start - b.start);\n if (covered.length === 0) return '';\n\n // Join with the document's own separator when the runs are adjacent in\n // `text` — pdf.js splits words at kerning and font changes, so a blanket\n // join(' ') would emit \"aga in\" for a single word. When runs are NOT\n // adjacent the rectangle missed the text between them, so substitute a\n // space rather than splicing in words the box does not cover. (Slicing\n // first-offset..last-offset the way buildPdfAnnotation does is safe there\n // — it only feeds a containment check — but here the result is the stored\n // quote, and on a two-column page it would swallow half of each column.)\n let quoted = slice(anchored, covered[0]);\n for (let i = 1; i < covered.length; i++) {\n const gap = anchored.text.slice(covered[i - 1].end, covered[i].start);\n quoted += (gap.trim() === '' ? gap : ' ') + slice(anchored, covered[i]);\n }\n return quoted.trim();\n}\n\nconst slice = (anchored: AnchoredText, item: PdfTextItem): string =>\n anchored.text.slice(item.start, item.end);\n\n/**\n * Fraction of a run's own area a rectangle must overlap for the run to count\n * as covered.\n *\n * Any intersection — the obvious rule, and `locate`'s rule for offsets — is not\n * survivable here, because a hand-drawn box is not a tight box. What decides\n * the threshold is the *headroom* between lines: word boxes run taller than\n * their glyphs, so the gap between one line's box and the next is far smaller\n * than the visible leading. Exact-quote rate measured over every text page of\n * two real scanned books, by how far the box misses:\n *\n * any 0.3 0.4 0.5 0.6\n * -2pt 98/99 98/83 98/49 60/16 2/ 0\n * -1pt 98/99 98/100 98/97 98/94 98/84\n * +2pt 45/ 2 98/97 98/99 98/99 98/100\n * +4pt 11/ 2 98/16 98/58 98/96 98/97\n * +6pt 9/ 0 51/ 8 64/11 98/16 98/38\n * (headroom ~2.0pt / ~0.9pt — the second book is set much tighter,\n * and on some of its pages adjacent word boxes overlap outright)\n *\n * A third book, 100 pages, varies run granularity instead — ~42 chars per run\n * against 25 and 14, i.e. whole lines as single runs — and 0.5 holds 100% from\n * -1pt to +6pt there. Across all three: >=94% from -1pt to +4pt every time.\n *\n * This also carries page skew, which is why it matters beyond hand-drawn boxes.\n * Tilting real runs and taking axis-aligned boxes after rotation, exact-quote\n * rate: 0.5 holds 100% to 0.25deg and 99% at 0.5deg, where `any` is already at\n * 54% and 34% — a tenth of a degree, invisible to the eye, is enough to wreck\n * it. Beyond ~1deg the limit is not this constant but `SAME_LINE_THRESHOLD_PT`,\n * which a drifting baseline exceeds, splitting one line into several rects.\n *\n * Any-intersection is exact only while the box is tight: 2pt of overshoot —\n * less than the height of a comma, and unavoidable with a mouse — and quotes\n * start picking up fragments of the lines above and below.\n *\n * 0.5 is the widest band holding on BOTH books, about 1pt under to 4pt over.\n * Lower thresholds look better on loosely-set pages and fail on tight ones\n * (0.3 drops to 16% at +4pt on the tighter book), which is exactly the way to\n * overfit this constant to one document. A hand drag overshoots far more often\n * than it undershoots, so the asymmetry is spent on the overshoot side.\n *\n * Consequence to know about: a run the box merely clips — a sliver of the\n * first or last word — falls below the threshold and is dropped. That is the\n * intended trade. Raising this admits neighbouring lines; lowering it drops\n * words from a box drawn slightly small.\n */\nexport const RUN_COVERAGE_THRESHOLD = 0.5;\n\nfunction covers(item: PdfTextItem, rect: PdfCoordinate): boolean {\n const overlapX = Math.min(item.x + item.width, rect.x + rect.width) - Math.max(item.x, rect.x);\n const overlapY = Math.min(item.y + item.height, rect.y + rect.height) - Math.max(item.y, rect.y);\n if (overlapX <= 0 || overlapY <= 0) return false;\n return overlapX * overlapY >= RUN_COVERAGE_THRESHOLD * item.width * item.height;\n}\n\nfunction groupItemsByPage(items: PdfTextItem[]): Map<number, PdfTextItem[]> {\n const map = new Map<number, PdfTextItem[]>();\n for (const item of items) {\n const existing = map.get(item.page);\n if (existing) {\n existing.push(item);\n } else {\n map.set(item.page, [item]);\n }\n }\n return map;\n}\n\n\n/**\n * Sorts text items into lines when their y coordinates are\n * within `sameLineThreshold` points of each other.\n * Sorted top-to-bottom (descending y in PDF space), then left-to-right.\n *\n * Returns 2D array:\n * Outer array = list of lines\n * Inner array = list of items on that line\n*/\nfunction groupItemsByLine(items: PdfTextItem[], sameLineThreshold: number): PdfTextItem[][] {\n // Sort top-to-bottom by y; if y is equal, sort left-to-right by x\n const sorted = [...items].sort((a, b) => b.y - a.y || a.x - b.x);\n const lines: PdfTextItem[][] = [];\n let currentLine: PdfTextItem[] = [];\n\n for (const item of sorted) {\n if (currentLine.length === 0 || Math.abs(item.y - currentLine[0].y) <= sameLineThreshold) {\n currentLine.push(item);\n } else {\n lines.push(currentLine);\n currentLine = [item];\n }\n }\n if (currentLine.length > 0) lines.push(currentLine);\n return lines;\n}\n","/**\n * Two-stage citation search over an extracted PDF text layer\n * (PDF-GENERATION P4).\n *\n * A citation's `exact` claim text comes from the authored source; the rendered\n * text layer diverges from it in exactly two measured ways (the P0 spike):\n * line breaks (`anchorRuns` joins runs with \" \\n\") and hyphenation (soft\n * hyphens are DROPPED — a hyphenated word yields its two halves with no hyphen\n * character anywhere).\n *\n * Two stages, in this order, never collapsed to one matcher:\n *\n * 1. STRICT — search a whitespace-normalized copy, offsets mapped back.\n * Bridges plain line breaks (\" \\n\" collapses to \" \").\n * 2. BREAK-AWARE — only on a strict miss. The line break becomes a distinct\n * marker character that may be absorbed in any inter-character gap, with\n * an optional space on either side (anchorRuns emits a space *then* the\n * newline). Ordinary spaces are NEVER wildcards, so \"abc\" cannot match\n * \"a b c\" — only a real break is absorbable.\n *\n * The ordering is the safety property: the permissive matcher runs only where\n * the strict one already failed, so it can never turn a working citation into\n * a wrong one — only a failure into an unlikely mismatch.\n */\nimport type { AnchoredText } from './pdf-anchoring';\n\n/** Distinct break marker — deliberately not a space (spaces are never wildcards). */\nconst BREAK_MARKER = '\u0001';\n\n/** Optional-break gap: the marker, with an optional space on either side. */\nconst BREAK_GAP = `(?: ?${BREAK_MARKER} ?)?`;\n\nconst escapeRegExp = (ch: string): string => ch.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nexport function findClaimSpan(\n anchored: AnchoredText,\n exact: string,\n): { start: number; end: number } | null {\n const needle = exact.replace(/\\s+/g, ' ').trim();\n if (needle.length === 0) return null;\n\n // ── Stage 1: strict, over a whitespace-normalized copy with an offset map ──\n let norm = '';\n const map: number[] = [];\n let pendingWsAt = -1;\n for (let i = 0; i < anchored.text.length; i++) {\n const ch = anchored.text[i]!;\n if (/\\s/.test(ch)) {\n if (norm.length > 0 && pendingWsAt < 0) pendingWsAt = i;\n continue;\n }\n if (pendingWsAt >= 0) {\n norm += ' ';\n map.push(pendingWsAt);\n pendingWsAt = -1;\n }\n norm += ch;\n map.push(i);\n }\n const idx = norm.indexOf(needle);\n if (idx >= 0) {\n return { start: map[idx]!, end: map[idx + needle.length - 1]! + 1 };\n }\n\n // ── Stage 2: break-aware, only on a miss ──\n const marker = anchored.text.replace(/\\n/g, BREAK_MARKER);\n const pattern = [...needle].map(escapeRegExp).join(BREAK_GAP);\n const match = new RegExp(pattern).exec(marker);\n if (match) {\n return { start: match.index, end: match.index + match[0].length };\n }\n\n return null;\n}\n","/**\n * Helper functions for working with W3C ResourceDescriptor\n */\n\nimport type { components } from './types';\nimport type { ResourceDescriptor } from './graph';\n\ntype Representation = components['schemas']['Representation'];\n\n/**\n * Get the resource ID from @id property\n *\n * @id is always a bare ID (UUID), never a full URI.\n */\nexport function getResourceId(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource) return undefined;\n return resource['@id'] || undefined;\n}\n\n/**\n * Get the primary representation (first or only representation)\n */\nexport function getPrimaryRepresentation(resource: ResourceDescriptor | undefined): Representation | undefined {\n if (!resource?.representations) return undefined;\n const reps = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n return reps[0];\n}\n\n/**\n * Get the media type from the primary representation\n */\nexport function getPrimaryMediaType(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.mediaType;\n}\n\n/**\n * Get the checksum from the primary representation\n */\nexport function getChecksum(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.checksum;\n}\n\n/**\n * Get the language from the primary representation\n */\nexport function getLanguage(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.language;\n}\n\n/**\n * Get storage URI from primary representation\n *\n * @param resource - ResourceDescriptor\n * @returns Storage URI or undefined\n */\nexport function getStorageUri(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.storageUri;\n}\n\n/**\n * Get creator agent from wasAttributedTo\n * Handles both single agent and array of agents\n *\n * @param resource - ResourceDescriptor\n * @returns First agent or undefined\n */\nexport function getCreator(resource: ResourceDescriptor | undefined): components['schemas']['Agent'] | undefined {\n if (!resource?.wasAttributedTo) return undefined;\n\n return Array.isArray(resource.wasAttributedTo)\n ? resource.wasAttributedTo[0]\n : resource.wasAttributedTo;\n}\n\n/**\n * Get derived-from URI\n * Handles both single URI and array of URIs\n *\n * @param resource - ResourceDescriptor\n * @returns First derivation URI or undefined\n */\nexport function getDerivedFrom(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource?.wasDerivedFrom) return undefined;\n\n return Array.isArray(resource.wasDerivedFrom)\n ? resource.wasDerivedFrom[0]\n : resource.wasDerivedFrom;\n}\n\n/**\n * Check if resource is archived (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if archived, false otherwise\n */\nexport function isArchived(resource: ResourceDescriptor | undefined): boolean {\n return resource?.archived === true;\n}\n\n/**\n * Get entity types from resource (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns Array of entity types, empty if not set\n */\nexport function getResourceEntityTypes(resource: ResourceDescriptor | undefined): string[] {\n return resource?.entityTypes || [];\n}\n\n/**\n * Check if resource is a draft (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if draft, false otherwise\n */\nexport function isDraft(resource: ResourceDescriptor | undefined): boolean {\n return resource?.isDraft === true;\n}\n\n/**\n * Map charset names to Node.js Buffer encoding names\n * Node.js Buffer.toString() supports: 'utf8', 'utf16le', 'latin1', 'base64', 'hex', 'ascii', 'binary', 'ucs2'\n *\n * @param charset - Charset name (e.g., \"UTF-8\", \"ISO-8859-1\", \"Windows-1252\")\n * @returns Node.js BufferEncoding\n */\nexport function getNodeEncoding(charset: string): BufferEncoding {\n const normalized = charset.toLowerCase().replace(/[-_]/g, '');\n\n // Map common charset names to Node.js encodings\n const charsetMap: Record<string, BufferEncoding> = {\n 'utf8': 'utf8',\n 'iso88591': 'latin1',\n 'latin1': 'latin1',\n 'ascii': 'ascii',\n 'usascii': 'ascii',\n 'utf16le': 'utf16le',\n 'ucs2': 'ucs2',\n 'binary': 'binary',\n 'windows1252': 'latin1', // Windows-1252 is a superset of Latin-1\n 'cp1252': 'latin1',\n };\n\n return charsetMap[normalized] || 'utf8';\n}\n\n/**\n * Decode a representation buffer to string using the correct charset\n * Extracts charset from media type and uses appropriate encoding\n *\n * @param buffer - The raw representation data\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=iso-8859-1\")\n * @returns Decoded string\n *\n * @example\n * ```typescript\n * const content = decodeRepresentation(buffer, \"text/plain; charset=utf-8\");\n * const legacy = decodeRepresentation(buffer, \"text/plain; charset=windows-1252\");\n * ```\n */\nexport function decodeRepresentation(buffer: Buffer, mediaType: string): string {\n // Extract charset from mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n const charset = (charsetMatch?.[1] || 'utf-8').toLowerCase();\n\n // Map to Node.js encoding\n const encoding = getNodeEncoding(charset);\n\n return buffer.toString(encoding);\n}\n","/**\n * Common error classes — the unified Semiont error hierarchy.\n *\n * `SemiontError` is the base every other Semiont error class extends:\n * `APIError` (http-transport), `BusRequestError` and `SemiontSessionError` (sdk),\n * `ValidationError`, `ScriptError`, `NotFoundError`, `UnauthorizedError`,\n * `ConflictError` (here), and `AWSError` (cli). Subclasses tighten the\n * `code` field to a literal-union for discriminated handling.\n */\n\n/**\n * Transport-neutral error vocabulary. Every transport that surfaces\n * errors over `ITransport.errors$` maps its native failure modes to one\n * of these codes — HTTP `APIError` maps from status code, in-process\n * transports map from local failure shape, gRPC would map from status\n * code, etc. Routing layers (e.g. `SemiontBrowser`'s session-expired /\n * permission-denied modal routing) match on this vocabulary so they\n * stay transport-agnostic.\n *\n * - `unauthorized` — auth required / token missing or expired (HTTP 401)\n * - `forbidden` — auth ok but lacks permission (HTTP 403)\n * - `not-found` — resource missing (HTTP 404)\n * - `conflict` — concurrent modification, duplicate, etc. (HTTP 409)\n * - `bad-request` — request malformed (HTTP 400)\n * - `unavailable` — backend unreachable, network error, 5xx\n * - `error` — unclassified fallback\n */\nexport type TransportErrorCode =\n | 'unauthorized'\n | 'forbidden'\n | 'not-found'\n | 'conflict'\n | 'bad-request'\n | 'unavailable'\n | 'error';\n\nexport class SemiontError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'SemiontError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class ValidationError extends SemiontError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'VALIDATION_ERROR', details);\n this.name = 'ValidationError';\n }\n}\n\nexport class ScriptError extends SemiontError {\n constructor(message: string, code: string = 'SCRIPT_ERROR', details?: Record<string, unknown>) {\n super(message, code, details);\n this.name = 'ScriptError';\n }\n}\n\nexport class NotFoundError extends SemiontError {\n constructor(resource: string, id?: string) {\n const message = id ? `${resource} with id '${id}' not found` : `${resource} not found`;\n super(message, 'NOT_FOUND', { resource, id });\n this.name = 'NotFoundError';\n }\n}\n\nexport class UnauthorizedError extends SemiontError {\n constructor(message: string = 'Unauthorized', details?: Record<string, unknown>) {\n super(message, 'UNAUTHORIZED', details);\n this.name = 'UnauthorizedError';\n }\n}\n\nexport class ConflictError extends SemiontError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'CONFLICT', details);\n this.name = 'ConflictError';\n }\n}\n","import { Observable, firstValueFrom, merge, throwError, TimeoutError } from 'rxjs';\nimport { catchError, defaultIfEmpty, filter, map, take, timeout } from 'rxjs/operators';\nimport { SemiontError } from './errors';\nimport type { EventMap, EventName } from './bus-protocol';\nimport type { ConnectionState } from './transport';\nimport { BUS_OPERATIONS, type BusOperationKey } from './bus-operations';\nimport { uuidV4 } from './id-generation';\n\n/**\n * The value a registered operation resolves to: the `response` field of its\n * result channel's payload, or `void` for a result channel that carries no\n * `response` (a confirmed-write ack with no data). Inferred from the registry,\n * so callers never annotate `busRequest`'s return type. Relies on the reply-shape\n * standard — see .plans/REPLY-SHAPE-STANDARD.md.\n */\nexport type BusReply<Op extends BusOperationKey> =\n EventMap[(typeof BUS_OPERATIONS)[Op]['result'] & EventName] extends { response: infer R }\n ? R\n : void;\n\nexport type BusRequestErrorCode =\n | 'bus.timeout'\n | 'bus.rejected'\n | 'bus.closed'\n | 'bus.bad-payload'\n | 'bus.unauthorized'\n | 'bus.forbidden'\n | 'bus.not-found';\n\nexport class BusRequestError extends SemiontError {\n declare code: BusRequestErrorCode;\n\n constructor(message: string, code: BusRequestErrorCode, details?: Record<string, unknown>) {\n super(message, code, details);\n this.name = 'BusRequestError';\n }\n}\n\n/**\n * Subset of ITransport that `busRequest` needs: a way to send a command and\n * a way to observe channels. Generic enough that an in-process transport\n * can satisfy it without round-tripping through HTTP.\n */\nexport interface BusRequestPrimitive {\n emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): Promise<void>;\n stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;\n /**\n * Connection state of the stream that carries replies. Required, not\n * optional (.plans/BUS-ATTACH-GATE.md D2): `busRequest` gates its emit on\n * this — no correlated emit before the reply path exists. Implementers back\n * it with a `BehaviorSubject`, so the current state arrives synchronously\n * on subscribe; a transport that cannot lose replies (in-process) reports\n * `'open'` until disposal.\n */\n state$: Observable<ConnectionState>;\n /**\n * Correlated-reply retention, client side (.plans/BUS-RESUMPTION.md\n * Phase 2 / SDK-DEBT S1). `busRequest` registers its correlationId here\n * BEFORE emitting and calls the returned disposer on every settle path;\n * a wire transport includes the currently-tracked ids as\n * `pendingReplies` in each subscribe body, so a reply published while\n * the connection was down is replayed from the server's retention\n * buffer on reconnect. OPTIONAL: an in-process transport that cannot\n * lose replies omits the surface and `busRequest` behaves as before.\n */\n trackReply?(correlationId: string): () => void;\n}\n\n/**\n * Request/reply over the bus, keyed by the operation's request channel.\n *\n * The `operation` is a `BusOperationKey` (a request channel declared in\n * `BUS_OPERATIONS`); the matching `result`/`failure` reply channels are looked\n * up from the registry, so a caller cannot pass a mismatched or unbridged reply\n * pair — the recurring unbridged-reply bug class is unrepresentable. Every\n * registry reply derives into `BRIDGED_CHANNELS` (see bridged-channels.ts), so\n * the transport always subscribes to it (cf.\n * .plans/bugs/gather-resource-complete-not-bridged.md, where the `gather:resource-*`\n * pair shipped unbridged with no compile/runtime signal).\n *\n * The return type is INFERRED from the registry (`BusReply<Op>` = the result\n * channel's `response` type, or `void`) — callers never annotate it. Every reply\n * is `{ correlationId, response: T }` (data) or `{ correlationId }` (void); see\n * .plans/REPLY-SHAPE-STANDARD.md. `busRequest` reads `e.response`.\n */\nexport async function busRequest<Op extends BusOperationKey>(\n bus: BusRequestPrimitive,\n operation: Op,\n payload: Record<string, unknown>,\n timeoutMs = 30_000,\n): Promise<BusReply<Op>> {\n const correlationId = uuidV4();\n const fullPayload = { ...payload, correlationId };\n const { result: resultChannel, failure: failureChannel } = BUS_OPERATIONS[operation];\n\n const result$ = merge(\n (bus.stream(resultChannel as keyof EventMap) as Observable<Record<string, unknown>>).pipe(\n filter((e) => e.correlationId === correlationId),\n map((e) => ({ ok: true as const, response: e.response as BusReply<Op> })),\n ),\n (bus.stream(failureChannel as keyof EventMap) as Observable<Record<string, unknown>>).pipe(\n filter((e) => e.correlationId === correlationId),\n map((e) => ({\n ok: false as const,\n error: new BusRequestError((e.message as string) ?? 'Bus request rejected', 'bus.rejected', {\n channel: failureChannel,\n correlationId,\n payload: e,\n }),\n })),\n ),\n ).pipe(\n take(1),\n timeout(timeoutMs),\n catchError((err) => {\n if (err instanceof TimeoutError) {\n return throwError(\n () =>\n new BusRequestError(\n `Bus request timed out after ${timeoutMs}ms on ${resultChannel}`,\n 'bus.timeout',\n { channel: operation, resultChannel, correlationId, timeoutMs },\n ),\n );\n }\n return throwError(() => err);\n }),\n // If the stream completes with no value — the bus was disposed before a\n // reply (e.g. during `semiont.dispose()` with a request in flight) —\n // resolve to a typed `bus.closed` result instead of letting `firstValueFrom`\n // throw rxjs `EmptyError`. An awaited caller then gets a clean\n // BusRequestError; an in-flight promise nobody is awaiting simply resolves,\n // so it can't surface as an unhandled rejection on dispose.\n // See .plans/bugs/busrequest-emptyerror-on-dispose.md.\n defaultIfEmpty({\n ok: false as const,\n error: new BusRequestError(\n `Bus closed before a reply on ${resultChannel}`,\n 'bus.closed',\n { channel: operation, resultChannel, correlationId },\n ),\n }),\n );\n\n // Subscribe before emitting so we don't miss an instantaneous reply\n // (which can happen with an in-process LocalTransport bus).\n const resultPromise = firstValueFrom(result$);\n\n // ── Attach gate (.plans/BUS-ATTACH-GATE.md) ─────────────────────────────\n // No correlated emit before the reply path exists: the measured failure was\n // an emit accepted (202) and answered while the session's subscribe stream\n // had not attached — the reply was published to nobody. Wait, inside the\n // SAME deadline (the timeout operator above is already ticking — D4), for\n // the transport to report the one deliverable state. D3 (amended\n // 2026-07-29): only `'open'` delivers; `'degraded'` is a dropped stream by\n // definition and waits like `connecting`/`reconnecting`. `'closed'` fails\n // fast — a request against a closed bus should not burn a timeout.\n const closedBeforeEmit = () => {\n // Detach the reply promise before throwing, same discipline as the emit\n // rejection path below: nobody will await it, and it must not surface\n // later as an unhandled rejection.\n resultPromise.catch(() => {});\n return new BusRequestError(`Bus closed before emit on ${operation}`, 'bus.closed', {\n channel: operation,\n correlationId,\n });\n };\n\n // Synchronous fast path: `state$` is BehaviorSubject-backed (see the\n // interface contract), so the current state lands during subscribe. Already\n // `'open'` → fall straight through to the emit with zero added microtasks —\n // the gate can only remove latency, never add it (D4).\n let currentState: ConnectionState | undefined;\n bus.state$.subscribe((s) => {\n currentState = s;\n }).unsubscribe();\n\n if (currentState === 'closed') {\n throw closedBeforeEmit();\n }\n let emitAllowed = currentState === 'open';\n if (!emitAllowed) {\n const gate = firstValueFrom(\n bus.state$.pipe(\n filter((s) => s === 'open' || s === 'closed'),\n take(1),\n // `state$` completed without ever attaching: treat as closed.\n defaultIfEmpty('closed' as ConnectionState),\n ),\n );\n const outcome = await Promise.race([\n gate,\n // Either settlement of the reply machinery means \"stop waiting, never\n // emit\": its timeout rejecting `bus.timeout` at `timeoutMs` (the same\n // moment it would fire today — D4), or its streams completing into the\n // `bus.closed` default above. The shared tail below carries it.\n resultPromise.then(\n () => 'settled' as const,\n () => 'settled' as const,\n ),\n ]);\n if (outcome === 'closed') {\n // The abandoned race arm cannot reject (filter + defaultIfEmpty), so\n // only the reply promise needs detaching — closedBeforeEmit does it.\n throw closedBeforeEmit();\n }\n // 'open' → the one emit below. 'settled' → skip the emit; awaiting the\n // reply at the tail rethrows its outcome. (D5 holds structurally either\n // way: nothing subscribes to state$ past this point, so a flap after\n // emission cannot re-emit.)\n emitAllowed = outcome === 'open';\n }\n\n // An emit rejection (e.g. /bus/emit 4xx) propagates to the caller — but the\n // caller then never awaits `resultPromise`, which is already subscribed and\n // will REJECT with `bus.timeout` at `timeoutMs` (the request never left, so\n // no reply can save it). Detach it before rethrowing so the doomed promise\n // can't surface later as an unhandled rejection. (`defaultIfEmpty` covers\n // only the disposed-bus case, where the stream completes and the promise\n // *resolves* `bus.closed`.) Found by the liveness harness's reject-emit\n // schedules (.plans/LIVENESS-AXIOMS.md, P1).\n //\n // Reply tracking (BUS-RESUMPTION.md Phase 2 / SDK-DEBT S1): register the\n // cid BEFORE the emit — a reconnect body built while the emit is in flight\n // must already carry it in `pendingReplies`, or a reply published in the\n // old-connection-death → new-connection-open gap sits in the server's\n // retention buffer unasked-for. Released on every settle path; the\n // never-emitted paths above (closed fast-fail, 'settled' race arm) never\n // reach this line, so they never track.\n let releaseTracking: (() => void) | undefined;\n if (emitAllowed) {\n releaseTracking = bus.trackReply?.(correlationId);\n try {\n await bus.emit(operation as keyof EventMap, fullPayload as EventMap[keyof EventMap]);\n } catch (emitError) {\n releaseTracking?.();\n releaseTracking = undefined;\n resultPromise.catch(() => {});\n throw emitError;\n }\n }\n\n try {\n const result = await resultPromise;\n if (!result.ok) {\n throw result.error;\n }\n return result.response;\n } finally {\n releaseTracking?.();\n }\n}\n","/**\n * Fuzzy Anchoring for W3C Web Annotation TextQuoteSelector\n *\n * Uses prefix/suffix context to disambiguate when the same text appears multiple times.\n * Implements fuzzy matching as specified in the W3C Web Annotation Data Model.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nexport interface TextPosition {\n start: number;\n end: number;\n}\n\nexport type MatchQuality = 'exact' | 'normalized' | 'case-insensitive' | 'fuzzy';\n\n/**\n * Normalize text for comparison - handles common document editing changes\n *\n * Collapses whitespace, converts curly quotes to straight quotes,\n * and normalizes common punctuation variations.\n */\nexport function normalizeText(text: string): string {\n return text\n .replace(/\\s+/g, ' ') // collapse whitespace\n .replace(/[\\u2018\\u2019]/g, \"'\") // curly single quotes → straight\n .replace(/[\\u201C\\u201D]/g, '\"') // curly double quotes → straight\n .replace(/\\u2014/g, '--') // em-dash → double hyphen\n .replace(/\\u2013/g, '-') // en-dash → hyphen\n .trim();\n}\n\n/**\n * Calculate Levenshtein distance between two strings\n * Used for fuzzy matching when exact text doesn't match\n */\nfunction levenshteinDistance(str1: string, str2: string): number {\n const len1 = str1.length;\n const len2 = str2.length;\n const matrix: number[][] = [];\n\n // Initialize matrix\n for (let i = 0; i <= len1; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= len2; j++) {\n matrix[0]![j] = j;\n }\n\n // Fill matrix\n for (let i = 1; i <= len1; i++) {\n for (let j = 1; j <= len2; j++) {\n const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;\n const deletion = matrix[i - 1]![j]! + 1;\n const insertion = matrix[i]![j - 1]! + 1;\n const substitution = matrix[i - 1]![j - 1]! + cost;\n matrix[i]![j] = Math.min(deletion, insertion, substitution);\n }\n }\n\n return matrix[len1]![len2]!;\n}\n\n/**\n * Pre-computed content strings for batch fuzzy matching.\n * Avoids recomputing normalizeText(content) and content.toLowerCase()\n * for every annotation when processing many annotations against the same content.\n *\n * `normalizedMap[i]` is the original-content index that normalized\n * character `i` came from. It has length `normalizedContent.length + 1`;\n * the final entry is `content.length` so a match that ends at the end of\n * the normalized string maps back to the end of the original. This map is\n * how `findBestTextMatch` recovers the *original* offset of a normalized\n * match — counting char-by-char with `normalizeText(singleChar)` is\n * wrong, because a lone whitespace char trims to `''` (contributing 0)\n * while in a full-string normalize it collapses to a single space\n * (contributing 1). That discrepancy shifted recovered offsets by the\n * number of whitespace runs before the match.\n */\nexport interface ContentCache {\n normalizedContent: string;\n normalizedMap: number[];\n lowerContent: string;\n}\n\n/**\n * Normalize text and, in the same pass, build a map from each normalized\n * character position back to the original-content index it came from.\n * The produced `normalized` string is identical to `normalizeText(input)`\n * — a test pins this equivalence so the two can't drift.\n */\nexport function normalizeTextWithMap(input: string): { normalized: string; map: number[] } {\n let normalized = '';\n const map: number[] = [];\n\n // First pass mirrors normalizeText exactly, char by char, recording the\n // origin index for every emitted normalized character.\n let pendingWhitespaceStart = -1; // origin index of an open whitespace run, or -1\n\n const flushWhitespace = () => {\n if (pendingWhitespaceStart !== -1) {\n // A whitespace run collapses to a single space, mapped to the run's\n // first char — but a *leading* run (nothing emitted yet) is dropped,\n // matching normalizeText's trailing `.trim()`.\n if (normalized.length > 0) {\n normalized += ' ';\n map.push(pendingWhitespaceStart);\n }\n pendingWhitespaceStart = -1;\n }\n };\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n if (/\\s/.test(ch)) {\n if (pendingWhitespaceStart === -1) pendingWhitespaceStart = i;\n continue;\n }\n flushWhitespace();\n if (ch === '‘' || ch === '’') {\n normalized += \"'\"; map.push(i);\n } else if (ch === '“' || ch === '”') {\n normalized += '\"'; map.push(i);\n } else if (ch === '—') {\n normalized += '--'; map.push(i); map.push(i);\n } else if (ch === '–') {\n normalized += '-'; map.push(i);\n } else {\n normalized += ch; map.push(i);\n }\n }\n // A trailing whitespace run is dropped by trim — do not flush it.\n\n // `normalizeText` applies `.trim()` last. Our run logic already drops a\n // trailing whitespace run; a leading run is dropped because flushWhitespace\n // only runs before a non-space char, so a run at the very start is never\n // emitted. Both ends match trim().\n map.push(input.length); // sentinel: one past the last normalized char\n return { normalized, map };\n}\n\n/**\n * Build a ContentCache for a given content string.\n * Call once per content, pass to findBestTextMatch/anchorAnnotation for all annotations.\n */\nexport function buildContentCache(content: string): ContentCache {\n const { normalized, map } = normalizeTextWithMap(content);\n return {\n normalizedContent: normalized,\n normalizedMap: map,\n lowerContent: content.toLowerCase()\n };\n}\n\n/**\n * Find best match for text in content using multi-strategy search\n *\n * Shared core logic used by both anchorAnnotation (render-time) and\n * reconcileSelector (write-time).\n *\n * @param content - Full text content to search within\n * @param searchText - The text to find\n * @param positionHint - Hint for where to search (TextPositionSelector.start)\n * @param cache - Pre-computed normalized/lowered content (from buildContentCache)\n * @returns Match with position and quality, or null if not found\n */\nexport function findBestTextMatch(\n content: string,\n searchText: string,\n positionHint: number | undefined,\n cache: ContentCache\n): { start: number; end: number; matchQuality: MatchQuality } | null {\n const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05)); // 5% tolerance or min 5 chars\n\n // Strategy 1: Exact match (case-sensitive, exact whitespace)\n const exactIndex = content.indexOf(searchText);\n if (exactIndex !== -1) {\n return {\n start: exactIndex,\n end: exactIndex + searchText.length,\n matchQuality: 'exact'\n };\n }\n\n // Strategy 2: Normalized match (handles whitespace/quote variations).\n // Map the normalized match position back to the original via the\n // precomputed index map. The naive char-by-char re-normalize is wrong:\n // a lone whitespace char trims to '' (0-width) but collapses to a single\n // space (1-width) in a full normalize, so it under-counts by the number\n // of whitespace runs before the match, shifting the recovered offset.\n const normalizedSearch = normalizeText(searchText);\n const normalizedIndex = cache.normalizedContent.indexOf(normalizedSearch);\n if (normalizedIndex !== -1) {\n const start = cache.normalizedMap[normalizedIndex] ?? 0;\n const end = cache.normalizedMap[normalizedIndex + normalizedSearch.length] ?? content.length;\n return {\n start,\n end,\n matchQuality: 'normalized'\n };\n }\n\n // Strategy 3: Case-insensitive match\n const lowerSearch = searchText.toLowerCase();\n const caseInsensitiveIndex = cache.lowerContent.indexOf(lowerSearch);\n if (caseInsensitiveIndex !== -1) {\n return {\n start: caseInsensitiveIndex,\n end: caseInsensitiveIndex + searchText.length,\n matchQuality: 'case-insensitive'\n };\n }\n\n // Strategy 4: Fuzzy match using Levenshtein distance with sliding window\n // Search near position hint if provided, otherwise search full content\n const windowSize = searchText.length;\n const searchRadius = Math.min(500, content.length);\n const searchStart = positionHint !== undefined\n ? Math.max(0, positionHint - searchRadius)\n : 0;\n const searchEnd = positionHint !== undefined\n ? Math.min(content.length, positionHint + searchRadius)\n : content.length;\n\n let bestMatch: { start: number; distance: number } | null = null;\n\n // Scan through content with sliding window\n for (let i = searchStart; i <= searchEnd - windowSize; i++) {\n const candidate = content.substring(i, i + windowSize);\n const distance = levenshteinDistance(searchText, candidate);\n\n if (distance <= maxFuzzyDistance) {\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = { start: i, distance };\n }\n }\n }\n\n if (bestMatch) {\n return {\n start: bestMatch.start,\n end: bestMatch.start + windowSize,\n matchQuality: 'fuzzy'\n };\n }\n\n return null;\n}\n\n/**\n * Verify that a position correctly points to the exact text\n * Useful for debugging and validation\n */\nexport function verifyPosition(\n content: string,\n position: TextPosition,\n expectedExact: string\n): boolean {\n const actualText = content.substring(position.start, position.end);\n return actualText === expectedExact;\n}\n","/**\n * Anchor a W3C Web Annotation to its rendered text.\n *\n * Render-time cleverness is deliberately limited to **verbatim** quote\n * matching. The annotation's two selectors are written to agree (the\n * write-side `reconcileSelector` + `buildTextAnnotation` invariant\n * guarantee `content.substring(start, end) === exact`). At render time the\n * only legitimate discrepancy is *positional drift*: the document grew or\n * shrank above the span after the annotation was written, so the offset is\n * stale but the exact text still exists, byte-identical, elsewhere. That is\n * the W3C-intended role of `TextQuoteSelector`, and it is safe because it\n * demands identical text — no normalization, no fuzzy matching, no\n * judgment call.\n *\n * Anything that would require *fuzzy* recovery (smart-quote folding,\n * whitespace collapse, Levenshtein) is out of scope here: a non-verbatim\n * mismatch means the content representation diverged or the stored record\n * is wrong, both of which are deterministic and belong upstream (canonical\n * content, or a corrected annotation event). The renderer does not guess —\n * it renders at the stored offset and flags the anchor low-confidence so\n * the discrepancy surfaces for an upstream fix.\n *\n * Returns `null` only when nothing usable is present; otherwise always\n * returns a position with a `strategy` and `confidence`.\n */\n\nexport type AnchorStrategy =\n /** Position hint pointed exactly at the exact text. Unambiguous. */\n | 'fast-path'\n /** Exact text appears once verbatim in the content. No tiebreak needed. */\n | 'unique-occurrence'\n /** Multiple verbatim occurrences; prefix+suffix uniquely identified one. */\n | 'context-disambiguated'\n /** Multiple verbatim candidates; position closest to hint chosen. */\n | 'position-tiebreaker'\n /** Exact text not found verbatim (or no quote); raw stored offset used,\n * flagged for upstream correction. */\n | 'position-fallback';\n\nexport type AnchorConfidence = 'high' | 'medium' | 'low';\n\nexport interface RenderedAnchor {\n start: number;\n end: number;\n strategy: AnchorStrategy;\n confidence: AnchorConfidence;\n}\n\nexport interface AnchorSelectors {\n position?: { start: number; end: number };\n quote?: { exact: string; prefix?: string; suffix?: string };\n}\n\n/**\n * Distance window for the position tiebreaker. Candidates closer than this\n * to the hint receive a non-zero position score; further candidates fall\n * back to zero. Tuned for typical document sizes; calibration tests pin\n * the boundary behaviour rather than the exact value.\n */\nexport const POSITION_WINDOW = 1024;\n\n/**\n * Score weights — kept as named constants so the calibration tests can\n * import them and pin the *relationships* rather than the magnitudes.\n *\n * Invariant: a full-context match always outranks any position score.\n * (`CONTEXT_FULL_WEIGHT * 2 > POSITION_WEIGHT_MAX`, accounting for\n * prefix+suffix each contributing the full weight.)\n */\nexport const CONTEXT_FULL_WEIGHT = 10;\nexport const CONTEXT_PARTIAL_WEIGHT = 5;\nexport const POSITION_WEIGHT_MAX = 5;\n\n/**\n * Locate the best-effort anchor for an annotation against the content the\n * renderer is about to display. Verbatim-only — see the module doc.\n */\nexport function anchorAnnotation(\n content: string,\n selectors: AnchorSelectors,\n): RenderedAnchor | null {\n const { position, quote } = selectors;\n\n // No quote selector. Position is the only signal; use it verbatim if\n // present and in-range, otherwise the annotation has no anchor.\n if (!quote || !quote.exact) {\n if (!position) return null;\n if (position.start < 0 || position.end > content.length || position.start >= position.end) {\n return null;\n }\n return {\n start: position.start,\n end: position.end,\n strategy: 'position-fallback',\n confidence: 'low',\n };\n }\n\n const { exact, prefix, suffix } = quote;\n\n // Fast path: position hint exactly matches the exact text.\n if (position) {\n const probeEnd = position.start + exact.length;\n if (\n position.start >= 0 &&\n probeEnd <= content.length &&\n content.substring(position.start, probeEnd) === exact\n ) {\n return {\n start: position.start,\n end: probeEnd,\n strategy: 'fast-path',\n confidence: 'high',\n };\n }\n }\n\n // Find all occurrences via exact indexOf. Cheap; bounded by content\n // size; sufficient for the common case where the renderer's content\n // matches the worker's content character-for-character.\n const occurrences = findAllOccurrences(content, exact);\n\n if (occurrences.length === 1) {\n const start = occurrences[0]!;\n return {\n start,\n end: start + exact.length,\n strategy: 'unique-occurrence',\n confidence: 'high',\n };\n }\n\n if (occurrences.length > 1) {\n const winner = pickByScore(content, occurrences, exact, prefix, suffix, position?.start);\n return winner;\n }\n\n // No verbatim occurrence. We do NOT fuzzy-match at render time — a\n // non-verbatim mismatch means the content diverged or the record is\n // wrong, which is an upstream concern. Render at the stored offset so the\n // highlight still appears, flagged low-confidence so the discrepancy is\n // visible and gets corrected at the source.\n if (position && position.start >= 0 && position.end <= content.length && position.start < position.end) {\n return {\n start: position.start,\n end: position.end,\n strategy: 'position-fallback',\n confidence: 'low',\n };\n }\n\n return null;\n}\n\nfunction findAllOccurrences(content: string, exact: string): number[] {\n const out: number[] = [];\n let i = content.indexOf(exact);\n while (i !== -1) {\n out.push(i);\n i = content.indexOf(exact, i + 1);\n }\n return out;\n}\n\n/**\n * Context match score at a candidate offset.\n * Returns full / partial / no-match per side (prefix and suffix), then\n * sums each side weighted by `CONTEXT_FULL_WEIGHT` / `CONTEXT_PARTIAL_WEIGHT`.\n *\n * \"Full\" means the stored context aligns exactly with the source text\n * adjacent to the candidate. \"Partial\" is the looser substring check —\n * the stored context appears somewhere in the candidate's surroundings\n * but isn't anchored to the edges. This is the same partial-match logic\n * the previous `findTextWithContext` used, captured here so the scorer\n * can use it as one signal among many instead of a hard filter.\n */\nfunction contextScoreAt(\n content: string,\n pos: number,\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n): { score: number; full: boolean } {\n let score = 0;\n let prefixFull = true;\n let suffixFull = true;\n\n if (prefix) {\n const adj = content.substring(Math.max(0, pos - prefix.length), pos);\n if (adj.endsWith(prefix)) {\n score += CONTEXT_FULL_WEIGHT;\n prefixFull = true;\n } else if (adj.includes(prefix.trim()) && prefix.trim().length > 0) {\n score += CONTEXT_PARTIAL_WEIGHT;\n prefixFull = false;\n } else {\n prefixFull = false;\n }\n }\n\n if (suffix) {\n const adj = content.substring(pos + exact.length, Math.min(content.length, pos + exact.length + suffix.length));\n if (adj.startsWith(suffix)) {\n score += CONTEXT_FULL_WEIGHT;\n suffixFull = true;\n } else if (adj.includes(suffix.trim()) && suffix.trim().length > 0) {\n score += CONTEXT_PARTIAL_WEIGHT;\n suffixFull = false;\n } else {\n suffixFull = false;\n }\n }\n\n // \"Full\" overall match means every provided context field aligned\n // exactly — no partial fallbacks. Used to bump confidence to high.\n const full =\n (prefix === undefined || prefixFull) &&\n (suffix === undefined || suffixFull) &&\n (prefix !== undefined || suffix !== undefined);\n\n return { score, full };\n}\n\nfunction positionScoreAt(pos: number, hint: number | undefined): number {\n if (hint === undefined) return 0;\n const distance = Math.abs(pos - hint);\n if (distance >= POSITION_WINDOW) return 0;\n return POSITION_WEIGHT_MAX * (1 - distance / POSITION_WINDOW);\n}\n\nfunction pickByScore(\n content: string,\n occurrences: number[],\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n hint: number | undefined,\n): RenderedAnchor {\n let bestPos = occurrences[0]!;\n let bestScore = -1;\n let bestContextFull = false;\n let bestHasAnyContextSignal = false;\n let bestHasAnyPositionSignal = false;\n\n for (const pos of occurrences) {\n const ctx = contextScoreAt(content, pos, exact, prefix, suffix);\n const positionScore = positionScoreAt(pos, hint);\n const total = ctx.score + positionScore;\n if (total > bestScore) {\n bestScore = total;\n bestPos = pos;\n bestContextFull = ctx.full;\n bestHasAnyContextSignal = ctx.score > 0;\n bestHasAnyPositionSignal = positionScore > 0;\n }\n }\n\n // Strategy + confidence classification:\n // - both context fields aligned exactly → high-confidence context-disambiguated\n // - some context aligned (full or partial), no position needed → context-disambiguated, medium\n // - position broke the tie (winning candidate has position signal but no context signal,\n // or context was equal across candidates) → position-tiebreaker\n // - no signal at all (all candidates scored zero) → position-tiebreaker, low confidence,\n // deterministic first-of-many fallback\n let strategy: AnchorStrategy;\n let confidence: AnchorConfidence;\n\n if (bestContextFull) {\n strategy = 'context-disambiguated';\n confidence = 'high';\n } else if (bestHasAnyContextSignal && !bestHasAnyPositionSignal) {\n strategy = 'context-disambiguated';\n confidence = 'medium';\n } else if (bestHasAnyContextSignal && bestHasAnyPositionSignal) {\n // Context partially matched and position helped break the tie.\n strategy = 'position-tiebreaker';\n confidence = 'medium';\n } else if (bestHasAnyPositionSignal) {\n strategy = 'position-tiebreaker';\n confidence = 'medium';\n } else {\n strategy = 'position-tiebreaker';\n confidence = 'low';\n }\n\n return {\n start: bestPos,\n end: bestPos + exact.length,\n strategy,\n confidence,\n };\n}\n","/**\n * Locale information\n * Copied from SDK for frontend use\n */\n\nexport interface LocaleInfo {\n code: string;\n nativeName: string;\n englishName: string;\n}\n\nexport const LOCALES: readonly LocaleInfo[] = [\n { code: 'ar', nativeName: 'العربية', englishName: 'Arabic' },\n { code: 'bn', nativeName: 'বাংলা', englishName: 'Bengali' },\n { code: 'cs', nativeName: 'Čeština', englishName: 'Czech' },\n { code: 'da', nativeName: 'Dansk', englishName: 'Danish' },\n { code: 'de', nativeName: 'Deutsch', englishName: 'German' },\n { code: 'el', nativeName: 'Ελληνικά', englishName: 'Greek' },\n { code: 'en', nativeName: 'English', englishName: 'English' },\n { code: 'es', nativeName: 'Español', englishName: 'Spanish' },\n { code: 'fa', nativeName: 'فارسی', englishName: 'Persian' },\n { code: 'fi', nativeName: 'Suomi', englishName: 'Finnish' },\n { code: 'fr', nativeName: 'Français', englishName: 'French' },\n { code: 'he', nativeName: 'עברית', englishName: 'Hebrew' },\n { code: 'hi', nativeName: 'हिन्दी', englishName: 'Hindi' },\n { code: 'id', nativeName: 'Bahasa Indonesia', englishName: 'Indonesian' },\n { code: 'it', nativeName: 'Italiano', englishName: 'Italian' },\n { code: 'ja', nativeName: '日本語', englishName: 'Japanese' },\n { code: 'ko', nativeName: '한국어', englishName: 'Korean' },\n { code: 'ms', nativeName: 'Bahasa Melayu', englishName: 'Malay' },\n { code: 'nl', nativeName: 'Nederlands', englishName: 'Dutch' },\n { code: 'no', nativeName: 'Norsk', englishName: 'Norwegian' },\n { code: 'pl', nativeName: 'Polski', englishName: 'Polish' },\n { code: 'pt', nativeName: 'Português', englishName: 'Portuguese' },\n { code: 'ro', nativeName: 'Română', englishName: 'Romanian' },\n { code: 'sv', nativeName: 'Svenska', englishName: 'Swedish' },\n { code: 'th', nativeName: 'ไทย', englishName: 'Thai' },\n { code: 'tr', nativeName: 'Türkçe', englishName: 'Turkish' },\n { code: 'uk', nativeName: 'Українська', englishName: 'Ukrainian' },\n { code: 'vi', nativeName: 'Tiếng Việt', englishName: 'Vietnamese' },\n { code: 'zh', nativeName: '中文', englishName: 'Chinese' },\n] as const;\n\n// Create lookup map for efficient access\nconst localeByCode = new Map<string, LocaleInfo>(\n LOCALES.map(locale => [locale.code.toLowerCase(), locale])\n);\n\n/**\n * Get locale information by code\n */\nexport function getLocaleInfo(code: string | undefined): LocaleInfo | undefined {\n if (!code) return undefined;\n return localeByCode.get(code.toLowerCase());\n}\n\n/**\n * Get the native name of a language by its locale code\n */\nexport function getLocaleNativeName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.nativeName;\n}\n\n/**\n * Get the English name of a language by its locale code\n */\nexport function getLocaleEnglishName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.englishName;\n}\n\n/**\n * Format locale code for display as \"Native Name (code)\"\n */\nexport function formatLocaleDisplay(code: string | undefined): string | undefined {\n if (!code) return undefined;\n\n const info = getLocaleInfo(code);\n if (!info) return code;\n\n return `${info.nativeName} (${code.toLowerCase()})`;\n}\n\n/**\n * Get all supported locale codes\n */\nexport function getAllLocaleCodes(): readonly string[] {\n return LOCALES.map(l => l.code);\n}\n","/**\n * SVG Utility Functions\n *\n * Utilities for creating, parsing, and manipulating W3C-compliant SVG selectors\n * for image annotation.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Create W3C-compliant SVG rectangle selector\n */\nexport function createRectangleSvg(start: Point, end: Point): string {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const width = Math.abs(end.x - start.x);\n const height = Math.abs(end.y - start.y);\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG polygon selector\n */\nexport function createPolygonSvg(points: Point[]): string {\n if (points.length < 3) {\n throw new Error('Polygon requires at least 3 points');\n }\n\n const pointsStr = points.map(p => `${p.x},${p.y}`).join(' ');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"${pointsStr}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG circle selector\n */\nexport function createCircleSvg(center: Point, radius: number): string {\n if (radius <= 0) {\n throw new Error('Circle radius must be positive');\n }\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"${center.x}\" cy=\"${center.y}\" r=\"${radius}\"/></svg>`;\n}\n\n/**\n * Parse SVG selector to extract shape type and data\n */\nexport function parseSvgSelector(svg: string): {\n type: 'rect' | 'polygon' | 'circle' | 'path';\n data: any;\n} | null {\n // Extract rectangle\n const rectMatch = svg.match(/<rect\\s+([^>]+)\\/>/);\n if (rectMatch && rectMatch[1]) {\n const attrs = rectMatch[1];\n const x = parseFloat(attrs.match(/x=\"([^\"]+)\"/)?.[1] || '0');\n const y = parseFloat(attrs.match(/y=\"([^\"]+)\"/)?.[1] || '0');\n const width = parseFloat(attrs.match(/width=\"([^\"]+)\"/)?.[1] || '0');\n const height = parseFloat(attrs.match(/height=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'rect',\n data: { x, y, width, height }\n };\n }\n\n // Extract polygon\n const polygonMatch = svg.match(/<polygon\\s+points=\"([^\"]+)\"/);\n if (polygonMatch && polygonMatch[1]) {\n const pointsStr = polygonMatch[1];\n const points = pointsStr.split(/\\s+/).map(pair => {\n const [x, y] = pair.split(',').map(parseFloat);\n return { x, y };\n });\n\n return {\n type: 'polygon',\n data: { points }\n };\n }\n\n // Extract circle\n const circleMatch = svg.match(/<circle\\s+([^>]+)\\/>/);\n if (circleMatch && circleMatch[1]) {\n const attrs = circleMatch[1];\n const cx = parseFloat(attrs.match(/cx=\"([^\"]+)\"/)?.[1] || '0');\n const cy = parseFloat(attrs.match(/cy=\"([^\"]+)\"/)?.[1] || '0');\n const r = parseFloat(attrs.match(/r=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'circle',\n data: { cx, cy, r }\n };\n }\n\n return null;\n}\n\n/**\n * Normalize coordinates from display space to image native resolution\n */\nexport function normalizeCoordinates(\n point: Point,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): Point {\n return {\n x: (point.x / displayWidth) * imageWidth,\n y: (point.y / displayHeight) * imageHeight\n };\n}\n\n/**\n * Scale entire SVG selector from display space to image native resolution\n */\nexport function scaleSvgToNative(\n svg: string,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): string {\n const parsed = parseSvgSelector(svg);\n if (!parsed) return svg;\n\n const scaleX = imageWidth / displayWidth;\n const scaleY = imageHeight / displayHeight;\n\n switch (parsed.type) {\n case 'rect': {\n const { x, y, width, height } = parsed.data;\n return createRectangleSvg(\n { x: x * scaleX, y: y * scaleY },\n { x: (x + width) * scaleX, y: (y + height) * scaleY }\n );\n }\n\n case 'circle': {\n const { cx, cy, r } = parsed.data;\n return createCircleSvg(\n { x: cx * scaleX, y: cy * scaleY },\n r * Math.min(scaleX, scaleY)\n );\n }\n\n case 'polygon': {\n const points = parsed.data.points.map((p: Point) => ({\n x: p.x * scaleX,\n y: p.y * scaleY\n }));\n return createPolygonSvg(points);\n }\n }\n\n return svg;\n}\n","/**\n * Selector reconciliation for write-time annotation construction.\n *\n * LLM-produced text offsets are guides, not authoritative anchors.\n * `reconcileSelector` takes whatever the LLM emitted and produces a\n * `TextQuoteSelector`-equivalent `start`/`end`/`exact`/`prefix`/`suffix`\n * that is provably consistent with the source content:\n *\n * - `content.substring(start, end) === exact`\n * - `content.substring(start - prefix.length, start) === prefix`\n * - `content.substring(end, end + suffix.length) === suffix`\n *\n * No caller spreads LLM-emitted prefix/suffix into the stored selector.\n * The shared helper extracts both from source at the corrected position,\n * so the no-overlap invariant holds by construction.\n *\n * Returns `null` when the LLM emitted text that doesn't appear in the\n * source. Callers filter; the helper doesn't decide for them.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nimport { findBestTextMatch, buildContentCache, type MatchQuality } from './fuzzy-anchor';\n\n/**\n * How the reconciliation arrived at the chosen offset. Carried into the\n * worker log so operators can audit ambiguous matches; the\n * `first-of-many` flag, in particular, is the signal that an annotation\n * *may* be anchored at the wrong occurrence and warrants review.\n */\nexport type AnchorMethod =\n /** Exact text appears once in the source — anchored unambiguously. */\n | 'unique-match'\n /** Multiple occurrences; LLM-emitted prefix/suffix picked one. */\n | 'context-recovered'\n /** Exact text not found verbatim; fuzzy match recovered it. */\n | 'fuzzy-match'\n /** Multiple occurrences, no context disambiguated — risky fallback. */\n | 'first-of-many';\n\nexport interface ReconciledSelector {\n start: number;\n end: number;\n /** Always a substring of the source content — never the LLM's emission. */\n exact: string;\n /** Extracted from source via extractContext — never the LLM's emission. */\n prefix?: string;\n /** Extracted from source via extractContext — never the LLM's emission. */\n suffix?: string;\n anchorMethod: AnchorMethod;\n /** Present when the fuzzy fallback recovered the match, naming how. */\n matchQuality?: MatchQuality;\n}\n\nexport interface LlmSelectorInput {\n exact: string;\n /** LLM-emitted context for disambiguation only — not for storage. */\n prefix?: string;\n /** LLM-emitted context for disambiguation only — not for storage. */\n suffix?: string;\n}\n\nconst CONTEXT_LENGTH = 64;\nconst MAX_EXTENSION = 32;\n// Minimum window of source text compared against an LLM-emitted prefix/suffix\n// when disambiguating multiple occurrences. The actual window grows to the\n// length of the LLM's prefix/suffix when that's longer — the prompts invite\n// up to 64 chars, and a fixed 32-char window can't `endsWith`/`includes` a\n// 64-char string, which would silently defeat disambiguation for exactly the\n// long, distinctive contexts that disambiguate best.\nconst DISAMBIGUATION_MIN_WINDOW = 32;\n\n/**\n * Extract prefix and suffix context for a `TextQuoteSelector` from\n * source content. Used internally by `reconcileSelector` after offsets\n * are reconciled, and exported for callers (e.g. UI-side selection\n * capture) that need the same extraction semantics.\n *\n * Extracts up to 64 characters before and after the selected text,\n * extending up to 32 additional chars to reach a word boundary so the\n * prefix/suffix is meaningful context rather than mid-word fragments.\n */\nexport function extractContext(\n content: string,\n start: number,\n end: number,\n): { prefix?: string; suffix?: string } {\n const result: { prefix?: string; suffix?: string } = {};\n\n if (start > 0) {\n let prefixStart = Math.max(0, start - CONTEXT_LENGTH);\n let extensionCount = 0;\n while (prefixStart > 0 && extensionCount < MAX_EXTENSION) {\n const char = content[prefixStart - 1];\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) break;\n prefixStart--;\n extensionCount++;\n }\n result.prefix = content.substring(prefixStart, start);\n }\n\n if (end < content.length) {\n let suffixEnd = Math.min(content.length, end + CONTEXT_LENGTH);\n let extensionCount = 0;\n while (suffixEnd < content.length && extensionCount < MAX_EXTENSION) {\n const char = content[suffixEnd];\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) break;\n suffixEnd++;\n extensionCount++;\n }\n result.suffix = content.substring(end, suffixEnd);\n }\n\n return result;\n}\n\n/**\n * Reconcile LLM-emitted offsets against the source. Returns a selector\n * whose `start`/`end` are verified to bracket `exact` in `content`, and\n * whose `prefix`/`suffix` are extracted from source — never carried\n * verbatim from the LLM.\n *\n * Returns `null` if `exact` cannot be found anywhere in the content,\n * even via fuzzy match. Callers filter null and log the drop.\n */\nexport function reconcileSelector(\n content: string,\n llm: LlmSelectorInput,\n): ReconciledSelector | null {\n const { exact, prefix: llmPrefix, suffix: llmSuffix } = llm;\n if (!exact) return null;\n\n // Find all verbatim occurrences.\n const occurrences: number[] = [];\n let i = content.indexOf(exact);\n while (i !== -1) {\n occurrences.push(i);\n i = content.indexOf(exact, i + 1);\n }\n\n if (occurrences.length === 1) {\n const start = occurrences[0]!;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'unique-match',\n };\n }\n\n if (occurrences.length > 1) {\n // Disambiguate via LLM-emitted prefix/suffix when present. Size the\n // comparison window to the LLM's prefix/suffix (with a floor), so a\n // 64-char prefix is matched against ≥64 chars of source — a fixed\n // smaller window can't `endsWith`/`includes` a longer LLM string.\n if (llmPrefix || llmSuffix) {\n const prefixWindow = Math.max(DISAMBIGUATION_MIN_WINDOW, llmPrefix?.length ?? 0);\n const suffixWindow = Math.max(DISAMBIGUATION_MIN_WINDOW, llmSuffix?.length ?? 0);\n for (const pos of occurrences) {\n const candPrefix = content.substring(Math.max(0, pos - prefixWindow), pos);\n const candSuffix = content.substring(\n pos + exact.length,\n Math.min(content.length, pos + exact.length + suffixWindow),\n );\n const prefixOk = !llmPrefix || candPrefix.endsWith(llmPrefix) || candPrefix.includes(llmPrefix.trim());\n const suffixOk = !llmSuffix || candSuffix.startsWith(llmSuffix) || candSuffix.includes(llmSuffix.trim());\n if (prefixOk && suffixOk) {\n const start = pos;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'context-recovered',\n };\n }\n }\n }\n\n // No context match. Fall back to the first occurrence and flag for\n // audit. Without an LLM-emitted locality hint there's no better\n // signal at this stage; `first-of-many` callers should log loudly so\n // operators can correct misanchored annotations.\n const start = occurrences[0]!;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'first-of-many',\n };\n }\n\n // No verbatim occurrences. Try fuzzy match (case-insensitive,\n // whitespace-normalized, Levenshtein with 5% tolerance). No position\n // hint to bias the search — fuzzy match scans content globally.\n const cache = buildContentCache(content);\n const fuzzy = findBestTextMatch(content, exact, undefined, cache);\n if (!fuzzy) return null;\n\n const actual = content.substring(fuzzy.start, fuzzy.end);\n const ctx = extractContext(content, fuzzy.start, fuzzy.end);\n return {\n start: fuzzy.start,\n end: fuzzy.end,\n // Use the actual source text, not the LLM's version — the LLM may\n // have emitted slightly different characters (smart vs straight\n // quotes, etc.) and we store what's verifiable.\n exact: actual,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'fuzzy-match',\n matchQuality: fuzzy.matchQuality,\n };\n}\n","/**\n * Text encoding utilities for consistent charset handling\n *\n * Ensures frontend decoding matches backend decoding by respecting\n * charset parameters in mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n */\n\n/**\n * Extract charset from mediaType parameter\n *\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=utf-8\")\n * @returns Charset name in lowercase (defaults to \"utf-8\")\n *\n * @example\n * extractCharset(\"text/plain; charset=iso-8859-1\") // \"iso-8859-1\"\n * extractCharset(\"text/plain\") // \"utf-8\"\n */\nexport function extractCharset(mediaType: string): string {\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n return (charsetMatch?.[1] || 'utf-8').toLowerCase();\n}\n\n/**\n * Decode ArrayBuffer to string using charset from mediaType\n *\n * Uses TextDecoder with the charset extracted from mediaType parameter.\n * This ensures the same character space is used for both annotation creation\n * (backend) and rendering (frontend).\n *\n * @param buffer - Binary data to decode\n * @param mediaType - Media type with optional charset parameter\n * @returns Decoded string in the original character space\n *\n * @example\n * const buffer = new Uint8Array([...]);\n * const text = decodeWithCharset(buffer, \"text/plain; charset=iso-8859-1\");\n */\nexport function decodeWithCharset(buffer: ArrayBuffer, mediaType: string): string {\n const charset = extractCharset(mediaType);\n\n // TextDecoder supports standard charset names\n // Common mappings that work in browsers:\n // - utf-8, utf-16, utf-16le, utf-16be\n // - iso-8859-1 through iso-8859-15\n // - windows-1252, windows-1251, etc.\n const decoder = new TextDecoder(charset);\n return decoder.decode(buffer);\n}\n","/**\n * Generic validation utilities for @semiont/http-transport\n *\n * Pure TypeScript validation with no external dependencies.\n * Safe to use in any JavaScript environment (Node.js, browser, Deno, etc.)\n */\n\n/**\n * Validation result types\n */\nexport type ValidationSuccess<T> = { success: true; data: T };\nexport type ValidationFailure = { success: false; error: string; details?: string[] };\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * JWT Token validation\n *\n * Validates JWT token format (header.payload.signature).\n * Does not verify signature - use for format validation only.\n */\nexport const JWTTokenSchema = {\n parse(token: unknown): string {\n if (typeof token !== 'string') {\n throw new Error('Token must be a string');\n }\n if (!token || token.length === 0) {\n throw new Error('Token is required');\n }\n // JWT format: header.payload.signature\n const jwtRegex = /^[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]*$/;\n if (!jwtRegex.test(token)) {\n throw new Error('Invalid JWT token format');\n }\n return token;\n },\n\n safeParse(token: unknown): ValidationResult<string> {\n try {\n const validated = this.parse(token);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Invalid JWT token',\n };\n }\n },\n};\n\n/**\n * Generic validation helper with error formatting\n *\n * Wraps any schema's parse method with try/catch and returns ValidationResult.\n *\n * @example\n * ```typescript\n * const result = validateData(JWTTokenSchema, 'eyJ...');\n * if (result.success) {\n * console.log('Valid token:', result.data);\n * } else {\n * console.error('Invalid:', result.error);\n * }\n * ```\n */\nexport function validateData<T>(\n schema: { parse(data: unknown): T },\n data: unknown\n): ValidationResult<T> {\n try {\n const validated = schema.parse(data);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Email validation helper\n *\n * Validates email format using RFC 5322 simplified regex.\n *\n * @param email - Email address to validate\n * @returns true if valid email format\n */\nexport function isValidEmail(email: string): boolean {\n if (email.length < 1 || email.length > 255) {\n return false;\n }\n // RFC 5322 simplified email regex\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n","/**\n * Media-type registry for Semiont\n *\n * One supported-types list, capability-tiered, keyed by the spec's\n * SupportedMediaType enum. Admission (registry membership) is the\n * create/yield gate: every member is storable, nameable, and uploadable.\n * The curated capabilities say what more the system can do with a type:\n *\n * - `render` — which viewer the UI mounts ('none' → metadata + download)\n * - `anchoring` — which annotation model applies: character-offset text\n * selectors vs spatial geometry (PDFs are spatial)\n * - `extractText` — how the Smelter gets embeddable text ('none' → skip\n * embedding, never mojibake)\n * - `authorable` — offered in the compose editor's format dropdown\n * - `uploadable` — big tent: true for every registry member\n *\n * Capabilities are orthogonal strategies, not a ladder: images render but\n * yield no text; PDFs yield text but aren't authorable. A \"tier\" is a\n * derived reading, not a stored fact.\n *\n * Import-leniency invariant: restore/import preserves archive mediaTypes\n * verbatim, so \"every stored mediaType is registry-valid\" holds only for\n * content that entered through the validated create/yield gate. No code\n * reading a stored mediaType may assume `capabilitiesOf()` succeeds — the\n * `undefined` branch is mandatory wherever stored types are read.\n */\n\nimport type { components } from './types';\n\nexport type SupportedMediaType = components['schemas']['SupportedMediaType'];\n\nexport type RenderMode = 'text' | 'image' | 'pdf' | 'none';\nexport type AnchoringModel = 'text-selector' | 'spatial' | 'none';\nexport type TextExtraction = 'decode' | 'pdf-text-layer' | 'none';\n\nexport interface MediaTypeCapabilities {\n /** Canonical file extension, with leading dot. */\n extension: `.${string}`;\n /** UI display name. */\n label: string;\n render: RenderMode;\n anchoring: AnchoringModel;\n extractText: TextExtraction;\n authorable: boolean;\n uploadable: boolean;\n /** Whether the generation worker can produce this type as a yield artifact.\n * Gate for `outputMediaType` — unsupported requests fail loudly, never\n * fall back to markdown under a mislabeled format. */\n generatable: boolean;\n}\n\n/** Storage tier: catalogued — stored, named, uploadable — but not\n * displayed or annotated. */\nconst storedBinary = (extension: `.${string}`, label: string): MediaTypeCapabilities => ({\n extension,\n label,\n render: 'none',\n anchoring: 'none',\n extractText: 'none',\n authorable: false,\n uploadable: true,\n generatable: false,\n});\n\n/** Storage tier, text-flavored: embedded (charset-aware decode), not rendered. */\nconst storedText = (extension: `.${string}`, label: string): MediaTypeCapabilities => ({\n ...storedBinary(extension, label),\n extractText: 'decode',\n});\n\n/**\n * The registry. `satisfies Record<SupportedMediaType, …>` is the\n * drift-lock: adding a type to the spec enum without a capabilities row\n * (or vice versa) is a compile error.\n *\n * Row order matters for `mediaTypeForExtension`: extension collisions\n * (.xml, .yaml, .js, .ts, .webm) resolve to the first row declaring the\n * extension.\n */\nexport const MEDIA_TYPES = {\n // Full-capability tier\n // `generatable: application/pdf` — the Typst renderer (PDF-GENERATION P3):\n // the model writes Typst, the worker's pinned binary compiles it.\n 'text/markdown': { extension: '.md', label: 'Markdown', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: true },\n 'text/plain': { extension: '.txt', label: 'Plain Text', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: true },\n 'text/html': { extension: '.html', label: 'HTML', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: false },\n 'application/json': { extension: '.json', label: 'JSON', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: false, uploadable: true, generatable: false },\n 'image/png': { extension: '.png', label: 'PNG image', render: 'image', anchoring: 'spatial', extractText: 'none', authorable: false, uploadable: true, generatable: false },\n 'image/jpeg': { extension: '.jpg', label: 'JPEG image', render: 'image', anchoring: 'spatial', extractText: 'none', authorable: false, uploadable: true, generatable: false },\n 'application/pdf': { extension: '.pdf', label: 'PDF', render: 'pdf', anchoring: 'spatial', extractText: 'pdf-text-layer', authorable: false, uploadable: true, generatable: true },\n\n // Storage tier — the big tent. Every row is a deliberate admission,\n // promotable by editing its row. Text-flavored rows embed (decode).\n\n // Text\n 'text/css': storedText('.css', 'CSS'),\n 'text/csv': storedText('.csv', 'CSV'),\n 'text/xml': storedText('.xml', 'XML'),\n\n // Structured-text application formats\n 'application/xml': storedText('.xml', 'XML'),\n 'application/yaml': storedText('.yaml', 'YAML'),\n 'application/x-yaml': storedText('.yaml', 'YAML'),\n\n // Programming languages\n 'text/javascript': storedText('.js', 'JavaScript'),\n 'application/javascript': storedText('.js', 'JavaScript'),\n 'text/x-typescript': storedText('.ts', 'TypeScript'),\n 'application/typescript': storedText('.ts', 'TypeScript'),\n 'text/x-python': storedText('.py', 'Python source'),\n 'text/x-java': storedText('.java', 'Java source'),\n 'text/x-c': storedText('.c', 'C source'),\n 'text/x-c++': storedText('.cpp', 'C++ source'),\n 'text/x-csharp': storedText('.cs', 'C# source'),\n 'text/x-go': storedText('.go', 'Go source'),\n 'text/x-rust': storedText('.rs', 'Rust source'),\n 'text/x-ruby': storedText('.rb', 'Ruby source'),\n 'text/x-php': storedText('.php', 'PHP source'),\n 'text/x-swift': storedText('.swift', 'Swift source'),\n 'text/x-kotlin': storedText('.kt', 'Kotlin source'),\n 'text/x-shell': storedText('.sh', 'Shell script'),\n\n // Documents\n 'application/msword': storedBinary('.doc', 'Word document (legacy)'),\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': storedBinary('.docx', 'Word document'),\n 'application/vnd.ms-excel': storedBinary('.xls', 'Excel spreadsheet (legacy)'),\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': storedBinary('.xlsx', 'Excel spreadsheet'),\n 'application/vnd.ms-powerpoint': storedBinary('.ppt', 'PowerPoint presentation (legacy)'),\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': storedBinary('.pptx', 'PowerPoint presentation'),\n\n // Archives\n 'application/zip': storedBinary('.zip', 'ZIP archive'),\n 'application/gzip': storedBinary('.gz', 'Gzip archive'),\n 'application/x-tar': storedBinary('.tar', 'TAR archive'),\n 'application/x-7z-compressed': storedBinary('.7z', '7z archive'),\n\n // Binaries\n 'application/octet-stream': storedBinary('.bin', 'Binary'),\n 'application/wasm': storedBinary('.wasm', 'WebAssembly module'),\n\n // Images beyond the rendered pair\n 'image/gif': storedBinary('.gif', 'GIF image'),\n 'image/webp': storedBinary('.webp', 'WebP image'),\n 'image/svg+xml': storedBinary('.svg', 'SVG image'),\n 'image/bmp': storedBinary('.bmp', 'BMP image'),\n 'image/tiff': storedBinary('.tiff', 'TIFF image'),\n 'image/x-icon': storedBinary('.ico', 'Icon'),\n\n // Video (before audio so .webm resolves to video)\n 'video/mp4': storedBinary('.mp4', 'MP4 video'),\n 'video/mpeg': storedBinary('.mpeg', 'MPEG video'),\n 'video/webm': storedBinary('.webm', 'WebM video'),\n 'video/ogg': storedBinary('.ogv', 'Ogg video'),\n 'video/quicktime': storedBinary('.mov', 'QuickTime video'),\n 'video/x-msvideo': storedBinary('.avi', 'AVI video'),\n\n // Audio\n 'audio/mpeg': storedBinary('.mp3', 'MP3 audio'),\n 'audio/wav': storedBinary('.wav', 'WAV audio'),\n 'audio/ogg': storedBinary('.ogg', 'Ogg audio'),\n 'audio/webm': storedBinary('.webm', 'WebM audio'),\n 'audio/aac': storedBinary('.aac', 'AAC audio'),\n 'audio/flac': storedBinary('.flac', 'FLAC audio'),\n\n // Fonts\n 'font/woff': storedBinary('.woff', 'WOFF font'),\n 'font/woff2': storedBinary('.woff2', 'WOFF2 font'),\n 'font/ttf': storedBinary('.ttf', 'TrueType font'),\n 'font/otf': storedBinary('.otf', 'OpenType font'),\n} satisfies Record<SupportedMediaType, MediaTypeCapabilities>;\n\n// String-indexable view for lookups with runtime strings.\nconst REGISTRY: Readonly<Record<string, MediaTypeCapabilities>> = MEDIA_TYPES;\n\n/**\n * Strip parameters (\"; charset=...\") and normalize case.\n * Replaces the inline `split(';')[0]` sites across the codebase.\n */\nexport function baseMediaType(format: string): string {\n return format.split(';')[0]!.trim().toLowerCase();\n}\n\n/**\n * Registry membership — the admission gate. Exact match: callers pass a\n * base type (see `baseMediaType`); strings carrying parameters are not\n * members.\n */\nexport function isSupportedMediaType(format: string): format is SupportedMediaType {\n return Object.hasOwn(MEDIA_TYPES, format);\n}\n\n/** Capabilities for a format (parameters tolerated), or undefined on registry miss. */\nexport function capabilitiesOf(format: string): MediaTypeCapabilities | undefined {\n return REGISTRY[baseMediaType(format)];\n}\n\n/**\n * Lenient extension lookup for naming foreign/imported content: '.dat' on\n * registry miss. Exporters use this — a vocabulary change must never\n * refuse to name restored data.\n */\nexport function extensionForMediaType(format: string): string {\n return capabilitiesOf(format)?.extension ?? '.dat';\n}\n\nconst EXTENSION_TO_MEDIA_TYPE: ReadonlyMap<string, SupportedMediaType> = (() => {\n const map = new Map<string, SupportedMediaType>();\n for (const type of Object.keys(MEDIA_TYPES) as SupportedMediaType[]) {\n const ext = MEDIA_TYPES[type].extension;\n if (!map.has(ext)) map.set(ext, type);\n }\n return map;\n})();\n\n/** Alternate spellings accepted by `mediaTypeForExtension`, mapped to\n * canonical registry extensions. */\nconst EXTENSION_ALIASES: Readonly<Record<string, string>> = {\n '.markdown': '.md',\n '.htm': '.html',\n '.jpeg': '.jpg',\n '.yml': '.yaml',\n};\n\n/**\n * Inverted registry: extension → media type, for the CLI and the upload\n * detection chain. Accepts 'md' or '.md', any case, and common alternate\n * spellings. Returns undefined for unknown extensions — detection chains\n * fall back to 'application/octet-stream' themselves.\n */\nexport function mediaTypeForExtension(ext: string): SupportedMediaType | undefined {\n const lower = ext.trim().toLowerCase();\n const dotted = lower.startsWith('.') ? lower : `.${lower}`;\n return EXTENSION_TO_MEDIA_TYPE.get(EXTENSION_ALIASES[dotted] ?? dotted);\n}\n\n/**\n * The Smelter's gate: how to get embeddable text from a format. Registry\n * rows answer directly; on a registry miss, base types under text/* decode\n * (RFC 2046 guarantees the text top-level type is textual — imported\n * unregistered text subtypes embed too), everything else is 'none'.\n */\nexport function textExtractionOf(format: string): TextExtraction {\n const caps = capabilitiesOf(format);\n if (caps) return caps.extractText;\n return baseMediaType(format).startsWith('text/') ? 'decode' : 'none';\n}\n\nconst REGISTRY_KEYS = Object.keys(MEDIA_TYPES) as SupportedMediaType[];\n\n/** Types offered in the compose editor's format dropdown. */\nexport const AUTHORABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].authorable,\n);\n\n/** Registry rows whose text the Smelter can extract. Rows only — the\n * text/* fallback in `textExtractionOf` isn't enumerable. */\nexport const EMBEDDABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].extractText !== 'none',\n);\n\n/** Types the generation worker can produce as a yield artifact — the\n * `outputMediaType` gate reads this, not a local table. */\nexport const GENERATABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].generatable,\n);\n","/**\n * Text Chunking Utilities\n *\n * Splits long text into overlapping chunks for embedding.\n * Each chunk is a passage that fits within the embedding model's context window.\n */\n\nexport interface ChunkingConfig {\n chunkSize: number; // approximate tokens per chunk\n overlap: number; // tokens of overlap between adjacent chunks\n}\n\nexport const DEFAULT_CHUNKING_CONFIG: ChunkingConfig = {\n chunkSize: 512,\n overlap: 64,\n};\n\n/**\n * Rough token count estimate: ~4 characters per token for English text.\n *\n * Exported as the single token-estimation heuristic: `chunkText` sizes chunks\n * with it, and inference/detection budget arithmetic must use the same\n * heuristic so estimates and chunk sizes agree.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Split text into overlapping chunks.\n *\n * Splits on paragraph boundaries when possible, falling back to sentence\n * boundaries, then word boundaries. Each chunk overlaps with the previous\n * by `overlap` tokens worth of text.\n */\nexport function chunkText(text: string, config: ChunkingConfig = DEFAULT_CHUNKING_CONFIG): string[] {\n if (text.length === 0) return [];\n const totalTokens = estimateTokens(text);\n if (totalTokens <= config.chunkSize) {\n return [text];\n }\n\n const chunkChars = config.chunkSize * 4;\n const overlapChars = config.overlap * 4;\n const chunks: string[] = [];\n let start = 0;\n\n while (start < text.length) {\n let end = Math.min(start + chunkChars, text.length);\n\n // Try to break at a paragraph boundary\n if (end < text.length) {\n const paraBreak = text.lastIndexOf('\\n\\n', end);\n if (paraBreak > start + chunkChars / 2) {\n end = paraBreak;\n } else {\n // Try sentence boundary\n const sentenceBreak = text.lastIndexOf('. ', end);\n if (sentenceBreak > start + chunkChars / 2) {\n end = sentenceBreak + 1;\n } else {\n // Try word boundary\n const wordBreak = text.lastIndexOf(' ', end);\n if (wordBreak > start + chunkChars / 2) {\n end = wordBreak;\n }\n }\n }\n }\n\n chunks.push(text.slice(start, end).trim());\n const nextStart = end - overlapChars;\n start = nextStart > start ? nextStart : end;\n if (start >= text.length) break;\n }\n\n return chunks.filter(c => c.length > 0);\n}\n","/**\n * Common type guard utilities\n */\n\n/**\n * Check if value is a string\n */\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\n/**\n * Check if value is a number (not NaN)\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value);\n}\n\n/**\n * Check if value is an object (not null, not array)\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Check if value is an array\n */\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\n/**\n * Check if value is a boolean\n */\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\n/**\n * Check if value is a function\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === 'function';\n}\n\n/**\n * Check if value is null\n */\nexport function isNull(value: unknown): value is null {\n return value === null;\n}\n\n/**\n * Check if value is undefined\n */\nexport function isUndefined(value: unknown): value is undefined {\n return value === undefined;\n}\n\n/**\n * Check if value is null or undefined\n */\nexport function isNullish(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n\n/**\n * Check if value is defined (not null or undefined)\n */\nexport function isDefined<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}","/**\n * DID (Decentralized Identifier) and W3C Agent utilities\n *\n * DID:WEB shapes used in Semiont:\n *\n * Knowledge base: did:web:<domain>\n * Person: did:web:<domain>:users:<email%40host>\n * Software: did:web:<domain>:agents:<provider>:<model>\n *\n * `<domain>` is the KB's committed `[site] domain` — one identity, with its\n * people and software peers named beneath it.\n *\n * `didToAgent` is the inverse: parse the DID, recognize whether the\n * subject is a person or a software peer, and return a typed Agent.\n *\n * Humans and software peers share the same identity *shape* (a DID\n * with a typed Agent on read). What differs is the path segment\n * (`:users:` vs `:agents:`) and the schema-typed fields each kind\n * carries on its Agent record.\n */\n\nimport type { components } from './types';\n\ntype Agent = components['schemas']['Agent'];\n\n/**\n * The knowledge base's own did:web identity, from its committed\n * `[site] domain` (`SemiontProject.siteDomain()`).\n *\n * Format: `did:web:<domain>` — the domain **verbatim, never encoded**. The\n * config already stores it in did:web colon-path form\n * (`the-ai-alliance.github.io:semiont-caselaw-kb`), so encoding those colons\n * would mint a string nothing else in the system produces. The launcher\n * mints the identical string in Go (`kbconfig.go` `didWeb()`), and the two\n * MUST agree byte-for-byte: the Browser joins discovered KBs to connected\n * ones on this value, and a mismatch fails silently — looking implemented\n * while never matching (.plans/KB-IDENTITY-VS-ADDRESS.md).\n *\n * A KB has no did when it declares no domain; identity is declared, never\n * defaulted or inferred from an address.\n */\nexport function kbDid(domain: string): string {\n return `did:web:${domain}`;\n}\n\n/**\n * Convert a user object to a DID:WEB identifier.\n *\n * Format: did:web:<domain>:users:<email%40domain>\n */\nexport function userToDid(user: { email: string; domain: string }): string {\n return `did:web:${user.domain}:users:${encodeURIComponent(user.email)}`;\n}\n\n/**\n * Convert a software peer's (provider, model) configuration to a DID:WEB\n * identifier. Pool-vs-individual deployment is not part of identity —\n * one DID per (provider, model) on this host.\n *\n * Format: did:web:<domain>:agents:<provider>:<model%2F-encoded>\n *\n * Model strings often contain `:` and `/` (e.g. `gemma2:27b`,\n * `library/llama3`); both must be URI-encoded so DID parsing isn't\n * ambiguous.\n */\nexport function agentToDid(agent: { domain: string; provider: string; model: string }): string {\n return `did:web:${agent.domain}:agents:${encodeURIComponent(agent.provider)}:${encodeURIComponent(agent.model)}`;\n}\n\n/**\n * Convert a user object to a typed Person Agent with a DID:WEB identifier.\n */\nexport function userToAgent(user: {\n id: string;\n domain: string;\n name: string | null;\n email: string;\n}): Agent {\n return {\n '@type': 'Person',\n '@id': userToDid(user),\n name: user.name || user.email,\n };\n}\n\n/**\n * Convert a software peer's configuration to a typed Software Agent.\n * The `name` is a stable human-friendly label, not a parseable join —\n * UI composes display from `provider`/`model` at render time.\n */\nexport function softwareToAgent(software: {\n domain: string;\n provider: string;\n model: string;\n parameters?: Record<string, unknown>;\n}): Agent {\n return {\n '@type': 'Software',\n '@id': agentToDid(software),\n name: `${software.provider} ${software.model}`,\n provider: software.provider,\n model: software.model,\n ...(software.parameters && { parameters: software.parameters }),\n };\n}\n\n/**\n * Parse a DID:WEB string into a typed Agent.\n *\n * Recognizes:\n * did:web:<host>:users:<email> → Person (name = decoded email)\n * did:web:<host>:agents:<provider>:<model> → Software (provider + model)\n *\n * Anything else falls back to a Person with the trailing segment as\n * `name`. This is the read-side inverse of `userToDid`/`agentToDid`.\n */\nexport function didToAgent(did: string | undefined | null): Agent {\n if (!did) {\n return { '@type': 'Person', '@id': 'unknown', name: 'unknown' };\n }\n const parts = did.split(':');\n\n // Find the kind segment, scanning from the right so we are not fooled\n // by `host:port` colons earlier in the string.\n const agentsIdx = parts.lastIndexOf('agents');\n const usersIdx = parts.lastIndexOf('users');\n\n if (agentsIdx >= 0 && agentsIdx === parts.length - 3) {\n const provider = decodeURIComponent(parts[agentsIdx + 1] ?? '');\n const model = decodeURIComponent(parts[agentsIdx + 2] ?? '');\n return {\n '@type': 'Software',\n '@id': did,\n name: `${provider} ${model}`,\n provider,\n model,\n };\n }\n\n if (usersIdx >= 0 && usersIdx === parts.length - 2) {\n const name = decodeURIComponent(parts[usersIdx + 1] ?? '');\n return {\n '@type': 'Person',\n '@id': did,\n name,\n };\n }\n\n // Unknown shape — preserve the DID as @id, derive a best-effort name\n // from the trailing segment. Treat as Person (the safer default for\n // unknown actors).\n const encoded = parts[parts.length - 1] || 'unknown';\n return {\n '@type': 'Person',\n '@id': did,\n name: decodeURIComponent(encoded),\n };\n}\n","/**\n * Environment validation utilities\n *\n * Pure functions - accept available environments as parameter instead of reading from filesystem\n */\n\nexport type Environment = string; // Allow any environment name\n\n/**\n * Type guard to check if a string is a valid Environment\n * @param value - The environment string to check\n * @param availableEnvironments - List of valid environment names\n */\nexport function isValidEnvironment(value: string | undefined, availableEnvironments: string[]): value is Environment {\n if (!value) return false;\n return availableEnvironments.includes(value);\n}\n\n/**\n * Parse environment string to Environment type\n * @param value - The environment string to parse\n * @param availableEnvironments - List of valid environment names\n * @returns Valid Environment type\n * @throws Error if environment is invalid or not provided\n */\nexport function parseEnvironment(value: string | undefined, availableEnvironments: string[]): Environment {\n if (!value) {\n throw new Error('Environment is required');\n }\n if (!isValidEnvironment(value, availableEnvironments)) {\n throw new Error(`Invalid environment: ${value}. Available environments: ${availableEnvironments.join(', ')}`);\n }\n return value;\n}\n\n/**\n * Validate and return environment or throw error\n * @param value - The environment string to validate\n * @param availableEnvironments - List of valid environment names\n * @throws Error if environment is invalid\n */\nexport function validateEnvironment(value: string | undefined, availableEnvironments: string[]): Environment {\n if (!value) {\n throw new Error('Environment is required');\n }\n if (!isValidEnvironment(value, availableEnvironments)) {\n throw new Error(`Invalid environment: ${value}. Available environments: ${availableEnvironments.join(', ')}`);\n }\n return value;\n}","/**\n * Configuration Error Class\n * \n * Custom error class for configuration validation and loading errors.\n * Provides structured error information with helpful suggestions.\n */\n\nexport class ConfigurationError extends Error {\n public override readonly cause?: Error;\n\n constructor(\n message: string,\n public environment?: string,\n public suggestion?: string,\n cause?: Error\n ) {\n super(message);\n this.name = 'ConfigurationError';\n this.cause = cause;\n }\n \n /**\n * Format the error nicely for CLI output\n */\n override toString(): string {\n let output = `❌ ${this.message}`;\n if (this.environment) {\n output += `\\n Environment: ${this.environment}`;\n }\n if (this.suggestion) {\n output += `\\n 💡 Suggestion: ${this.suggestion}`;\n }\n return output;\n }\n}","/**\n * Platform Types Module\n *\n * Re-exports PlatformType from schema-generated types.\n * Platforms represent WHERE services run (infrastructure targets).\n */\n\nimport { PlatformType as SchemaPlatformType } from './config.types';\n\n/**\n * Platform type literals from JSON Schema\n * These represent the infrastructure targets where services can be deployed\n */\nexport type PlatformType = SchemaPlatformType;\n\n/**\n * Type guard to check if a string is a valid platform type\n *\n * @param value - Value to check\n * @returns True if value is a valid PlatformType\n */\nexport function isValidPlatformType(value: string): value is PlatformType {\n return ['aws', 'container', 'posix', 'external'].includes(value);\n}\n\n/**\n * Get all valid platform types\n *\n * @returns Array of all platform types\n */\nexport function getAllPlatformTypes(): PlatformType[] {\n return ['aws', 'container', 'posix', 'external'];\n}","/**\n * Knowledge-graph view derivation (CONTEXT-UNIFICATION P3, Q1=A).\n *\n * A pure function over the core `KnowledgeGraph` type, so both `@semiont/make-meaning` (the matcher)\n * and `@semiont/jobs` (the generation prompt builder) can share one derivation. `buildKnowledgeGraph`\n * — which queries the graph DB — stays in make-meaning; this only transforms an already-built graph.\n *\n * Reports the graph as-is (Option A): missing-view citers are kept (the citation edge reflects a real\n * reference event); the only filter is excluding the focal annotation from siblings (an annotation\n * isn't its own sibling). Peer connections are edges out of `mainResourceId`; citations and\n * `annotation-of` edges point INTO it. The graph is a projection of the event log (the system of\n * record), read here because it is the queryable projection at gather time.\n */\nimport type { components } from './types';\n\ntype KnowledgeGraph = components['schemas']['KnowledgeGraph'];\n\nexport interface GraphViews {\n connections: { resourceId: string; resourceName: string; entityTypes: string[]; bidirectional: boolean }[];\n citedBy: { resourceId: string; resourceName: string }[];\n citedByCount: number;\n siblingEntityTypes: string[];\n}\n\nexport function deriveViews(\n graph: KnowledgeGraph,\n mainResourceId: string,\n focalAnnotationId?: string,\n): GraphViews {\n const nodeById = new Map(graph.nodes.map((n) => [n.id, n] as const));\n\n const connections: GraphViews['connections'] = [];\n const citedBy: GraphViews['citedBy'] = [];\n for (const edge of graph.edges) {\n if (edge.type === 'citation') {\n if (edge.target !== mainResourceId) continue;\n const node = nodeById.get(edge.source);\n citedBy.push({ resourceId: edge.source, resourceName: node?.label ?? edge.source });\n } else if (edge.source === mainResourceId) {\n const node = nodeById.get(edge.target);\n connections.push({\n resourceId: edge.target,\n resourceName: node?.label ?? edge.target,\n entityTypes: node?.entityTypes ?? [],\n bidirectional: edge.bidirectional ?? false,\n });\n }\n }\n\n const siblingEntityTypes = new Set<string>();\n for (const node of graph.nodes) {\n if (node.type === 'annotation' && node.id !== focalAnnotationId) {\n for (const et of node.entityTypes ?? []) siblingEntityTypes.add(et);\n }\n }\n\n return {\n connections,\n citedBy,\n citedByCount: citedBy.length,\n siblingEntityTypes: Array.from(siblingEntityTypes),\n };\n}\n","/**\n * Bounded retry with exponential backoff.\n *\n * Exists for startup-critical network calls in long-running peers (worker,\n * smelter, weaver): each authenticates against the KS the moment its\n * container starts, and the backend may not be reachable for a few seconds\n * (backend restart, container-network warm-up). Orchestration runs these\n * processes with `--rm` and no restart policy, so a process that dies on\n * the first `TypeError: fetch failed` is dead for good — the retry window\n * here is the only recovery it gets.\n */\n\nexport interface RetryPolicy {\n /** Total attempts, including the first one. */\n attempts: number;\n /** Delay before the second attempt; doubles each retry. */\n initialDelayMs: number;\n /** Ceiling for the doubled delay. */\n maxDelayMs: number;\n}\n\nexport interface RetryAttemptInfo {\n /** 1-based number of the attempt that just failed. */\n attempt: number;\n /** Total attempt budget from the policy. */\n attempts: number;\n /** How long we wait before the next attempt. */\n delayMs: number;\n error: unknown;\n}\n\n/**\n * Default policy for startup connections to the backend: 8 attempts with\n * delays 1s, 2s, 4s, then capped at 8s — ~39s of patience before giving up.\n */\nexport const STARTUP_FETCH_RETRY: RetryPolicy = {\n attempts: 8,\n initialDelayMs: 1_000,\n maxDelayMs: 8_000,\n};\n\n/**\n * True for the errors `fetch` throws when the connection itself fails —\n * undici's `TypeError: fetch failed` (ECONNREFUSED, ENOTFOUND, reset,\n * timeout — the socket error rides in `cause`). Deliberately false for\n * HTTP-level failures (a 401 means the backend is UP and rejected us;\n * retrying won't change its mind) and for programming errors.\n */\nexport function isTransientFetchError(error: unknown): boolean {\n if (!(error instanceof TypeError)) return false;\n if (error.message === 'fetch failed') return true;\n const code = (error.cause as { code?: string } | undefined)?.code;\n return typeof code === 'string' && code.length > 0;\n}\n\n/**\n * Run `fn`, retrying on errors `isRetryable` accepts, with exponential\n * backoff per `policy`. `onRetry` fires before each wait — the caller's\n * hook for logging the attempt. The final error (retryable budget\n * exhausted, or the first non-retryable one) is rethrown verbatim.\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n isRetryable: (error: unknown) => boolean,\n policy: RetryPolicy,\n onRetry?: (info: RetryAttemptInfo) => void,\n): Promise<T> {\n let delayMs = policy.initialDelayMs;\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= policy.attempts || !isRetryable(error)) throw error;\n onRetry?.({ attempt, attempts: policy.attempts, delayMs, error });\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n delayMs = Math.min(delayMs * 2, policy.maxDelayMs);\n }\n }\n}\n","/**\n * Sharding Utilities\n *\n * Shared utilities for consistent sharding across all storage layers —\n * the event log and view storage (@semiont/event-sourcing) and the\n * anchored-text store (@semiont/content) all lay files out as\n * `{ab}/{cd}/<key>` through `getShardPath`. Hoisted here (PERSIST-ANCHORS\n * P1a) so both importers share one implementation: a second sharding\n * implementation is how two trees end up disagreeing about where\n * something lives.\n *\n * Pure string/number math — no node dependencies — so it is safe on\n * core's browser-facing root export.\n */\n\n/**\n * TEMPORARY: Simple modulo-based hash sharding\n *\n * ⚠️ TODO: Replace with proper Jump Consistent Hash implementation\n *\n * This is a TEMPORARY implementation using simple modulo. It works and provides\n * good distribution, but does NOT provide the minimal reshuffling property of\n * Jump Consistent Hash when changing bucket counts.\n *\n * The proper implementation should use Google's Jump Consistent Hash algorithm:\n * Reference: \"A Fast, Minimal Memory, Consistent Hash Algorithm\" by Lamping & Veach (2014)\n * https://arxiv.org/abs/1406.2294\n *\n * Working implementations exist in npm packages like:\n * - jumphash (https://www.npmjs.com/package/jumphash)\n * - jump-gouache (https://github.com/bhoudu/jump-gouache)\n *\n * The algorithm requires proper 64-bit integer handling with BigInt to avoid\n * precision loss in JavaScript. The previous attempt failed due to incorrect\n * BigInt arithmetic in the while loop condition.\n *\n * Until replaced, this modulo approach will cause ALL data to be reshuffled\n * if bucket count changes, rather than the optimal O(n/k) reshuffling that\n * Jump Consistent Hash provides.\n *\n * @param key - The key to hash (a resource id or content checksum)\n * @param numBuckets - Number of shards/buckets (default: 65536 for 4-hex sharding)\n * @returns Shard number (0 to numBuckets-1)\n */\nexport function jumpConsistentHash(key: string, numBuckets: number = 65536): number {\n const hash = hashToUint32(key);\n return hash % numBuckets;\n}\n\n/**\n * Hash string to 32-bit unsigned integer\n */\nfunction hashToUint32(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash = hash & 0xFFFFFFFF;\n }\n return Math.abs(hash);\n}\n\n/**\n * Convert shard number to 4-hex directory path (ab/cd)\n *\n * @param shardId - Shard number (0-65535)\n * @returns Path segments like ['ab', 'cd']\n */\nfunction shardIdToPath(shardId: number): [string, string] {\n if (shardId < 0 || shardId >= 65536) {\n throw new Error(`Invalid shard ID: ${shardId}. Must be 0-65535 for 4-hex sharding.`);\n }\n\n const shardHex = shardId.toString(16).padStart(4, '0');\n const ab = shardHex.substring(0, 2);\n const cd = shardHex.substring(2, 4);\n\n return [ab, cd];\n}\n\n/**\n * Get 4-hex shard path for a key\n *\n * @param key - The key to hash (a resource id or content checksum)\n * @param numBuckets - Number of shards (default: 65536)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function getShardPath(key: string, numBuckets: number = 65536): [string, string] {\n const shardId = jumpConsistentHash(key, numBuckets);\n return shardIdToPath(shardId);\n}\n","/**\n * Browser ↔ launcher KB discovery (BROWSER-KB-DISCOVERY).\n *\n * The launcher publishes its export view at `<stateDir>/discovery/kbs.json`,\n * mounted read-only into the frontend container at `/discovery` and served\n * by the frontend image at this URL path. One TS-side name for that URL: the\n * frontend server's tests fetch this constant, so prefix/filename drift\n * between the server and consumers is a failing test — mirroring for the URL\n * what the DiscoveryDocument schema does for the payload. (The launcher's Go\n * side keeps its own constant; the plan doc is the cross-language record.)\n */\nexport const DISCOVERY_URL_PATH = '/discovery/kbs.json';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/identifiers.ts","../src/persisted-events.ts","../src/bus-protocol.ts","../src/event-utils.ts","../src/operators/burst-buffer.ts","../src/serialize-per-key.ts","../src/logger.ts","../src/annotation-utils.ts","../src/id-generation.ts","../src/annotation-assembly.ts","../src/web-annotation-utils.ts","../src/pdf-coordinates.ts","../src/pdf-anchoring.ts","../src/pdf-citation-search.ts","../src/resource-utils.ts","../src/errors.ts","../src/bus-request.ts","../src/fuzzy-anchor.ts","../src/anchor-annotation.ts","../src/locales.ts","../src/svg-utils.ts","../src/text-context.ts","../src/text-encoding.ts","../src/validation.ts","../src/media-types.ts","../src/chunking.ts","../src/type-guards.ts","../src/did-utils.ts","../src/config/environment-validator.ts","../src/config/configuration-error.ts","../src/config/platform-types.ts","../src/knowledge-graph-views.ts","../src/retry.ts","../src/shard-utils.ts","../src/discovery.ts"],"names":["resourceUri","baseUrl","annotationUri","right","map","ctx","start","end","email"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Branded identifier types for compile-time type safety.\n *\n * These types prevent mixing up resource IDs, annotation IDs, and user IDs\n * at compile time while having zero runtime overhead.\n *\n * URI types (ResourceUri, AnnotationUri) are in @semiont/http-transport\n * since they deal with HTTP URIs returned by the API.\n */\n\n// Branded type definitions for IDs only\nexport type ResourceId = string & { readonly __brand: 'ResourceId' };\nexport type AnnotationId = string & { readonly __brand: 'AnnotationId' };\nexport type UserId = string & { readonly __brand: 'UserId' };\n\n// Type guards with runtime validation\nexport function isResourceId(value: string): value is ResourceId {\n return !value.includes('/');\n}\n\nexport function isAnnotationId(value: string): value is AnnotationId {\n return !value.includes('/');\n}\n\n// Factory functions with runtime validation\nexport function resourceId(id: string): ResourceId {\n if (id.includes('/')) {\n throw new TypeError(`Expected ResourceId, got URI: ${id}`);\n }\n return id as ResourceId;\n}\n\nexport function annotationId(id: string): AnnotationId {\n if (id.includes('/')) {\n throw new TypeError(`Expected AnnotationId, got URI: ${id}`);\n }\n return id as AnnotationId;\n}\n\nexport function userId(id: string): UserId {\n return id as UserId;\n}\n","/**\n * Persisted Events\n *\n * The event types that get appended to the JSONL event log.\n * Each maps a type string to its OpenAPI payload schema.\n * The PersistedEvent union derives from this catalog.\n */\n\nimport type { components } from './types';\nimport type { AnnotationId, ResourceId } from './identifiers';\nimport type { Annotation } from './annotation-types';\nimport type { EventBase } from './event-base';\n\n// Branded payload overrides — the OpenAPI schemas reference the raw\n// `Annotation` type with `id: string`. At the TypeScript layer we narrow\n// to the branded `Annotation` so consumers read `payload.annotation.id`\n// as `AnnotationId` without an upcast at every seam.\ntype AnnotationAddedPayload =\n components['schemas']['AnnotationAddedPayload'] & { annotation: Annotation };\ntype AnnotationRemovedPayload =\n components['schemas']['AnnotationRemovedPayload'] & { annotationId: AnnotationId };\ntype AnnotationBodyUpdatedPayload =\n components['schemas']['AnnotationBodyUpdatedPayload'] & { annotationId: AnnotationId };\n\n// ── The Catalog ──────────────────────────────────────────────────────────────\n\n/**\n * Maps each persisted event type string to its OpenAPI payload schema.\n * Single source of truth for \"what events get written to the log.\"\n */\ntype PersistedEventCatalog = {\n 'yield:created': components['schemas']['ResourceCreatedPayload'];\n 'yield:cloned': components['schemas']['ResourceClonedPayload'];\n 'yield:updated': components['schemas']['ResourceUpdatedPayload'];\n 'yield:moved': components['schemas']['ResourceMovedPayload'];\n 'yield:representation-added': components['schemas']['RepresentationAddedPayload'];\n 'yield:representation-removed': components['schemas']['RepresentationRemovedPayload'];\n 'mark:added': AnnotationAddedPayload;\n 'mark:removed': AnnotationRemovedPayload;\n 'mark:body-updated': AnnotationBodyUpdatedPayload;\n 'mark:archived': components['schemas']['ResourceArchivedPayload'];\n 'mark:unarchived': components['schemas']['ResourceUnarchivedPayload'];\n 'mark:entity-tag-added': components['schemas']['EntityTagChangedPayload'];\n 'mark:entity-tag-removed': components['schemas']['EntityTagChangedPayload'];\n 'frame:entity-type-added': components['schemas']['EntityTypeAddedPayload'];\n 'frame:tag-schema-added': components['schemas']['TagSchemaAddedPayload'];\n 'job:started': components['schemas']['JobStartedPayload'];\n 'job:completed': components['schemas']['JobCompletedPayload'];\n 'job:failed': components['schemas']['JobFailedPayload'];\n};\n\n// ── Derived types ────────────────────────────────────────────────────────────\n\n/** System event types — persisted events that have no resourceId. */\ntype SystemEventType = 'frame:entity-type-added' | 'frame:tag-schema-added';\n\n/** Extract the concrete persisted event type for a given type string. */\nexport type EventOfType<K extends keyof PersistedEventCatalog> =\n K extends SystemEventType\n ? EventBase & { type: K; payload: PersistedEventCatalog[K] }\n : EventBase & { type: K; resourceId: ResourceId; payload: PersistedEventCatalog[K] };\n\n/** The union of all persisted event types. Discriminated on `type`. */\nexport type PersistedEvent = {\n [K in keyof PersistedEventCatalog]: EventOfType<K>\n}[keyof PersistedEventCatalog];\n\nexport type PersistedEventType = PersistedEvent['type'];\n\n/**\n * Runtime list of every persisted event type.\n *\n * Single source of truth for code that needs to enumerate event types at\n * runtime — most importantly the per-resource `events-stream` SSE route,\n * which subscribes to all of them. The exhaustiveness check below makes\n * it impossible to add a new member to `PersistedEventCatalog` without\n * also adding it here: forgetting fails to typecheck rather than silently\n * dropping the event from the events-stream.\n */\nexport const PERSISTED_EVENT_TYPES = [\n 'yield:created',\n 'yield:cloned',\n 'yield:updated',\n 'yield:moved',\n 'yield:representation-added',\n 'yield:representation-removed',\n 'mark:added',\n 'mark:removed',\n 'mark:body-updated',\n 'mark:archived',\n 'mark:unarchived',\n 'mark:entity-tag-added',\n 'mark:entity-tag-removed',\n 'frame:entity-type-added',\n 'frame:tag-schema-added',\n 'job:started',\n 'job:completed',\n 'job:failed',\n] as const satisfies readonly PersistedEventType[];\n\n// Compile-time exhaustiveness: if PersistedEventType gains a member that\n// PERSISTED_EVENT_TYPES is missing, this assignment fails to typecheck.\n// The ERROR object names the missing-member case so the build error is\n// self-explanatory.\ntype _ExhaustivePersistedEventTypes =\n Exclude<PersistedEventType, typeof PERSISTED_EVENT_TYPES[number]> extends never\n ? true\n : { ERROR: 'PERSISTED_EVENT_TYPES is missing members of PersistedEventType' };\nconst _persistedEventTypesExhaustive: _ExhaustivePersistedEventTypes = true;\nvoid _persistedEventTypesExhaustive;\n\n/** Input type for appendEvent — PersistedEvent without id/timestamp (assigned at persistence time). */\nexport type EventInput = Omit<PersistedEvent, 'id' | 'timestamp'>;\n","// ⚠ GENERATED FILE — do not edit.\n//\n// Authority: specs/src/bus/registry.json (channels, payloads, operations)\n// Regenerate: node scripts/bus/generate-ts.mjs\n// Go counterpart: node scripts/bus/generate-go.mjs → packages/sdk-go/bus\n//\n// Payload schemas themselves live in the OpenAPI components; the registry\n// names which one each channel carries. Add or change a channel THERE.\n\n/**\n * Bus Protocol\n *\n * The complete EventMap for the RxJS EventBus. Every channel name and\n * its payload type is defined here — domain events, commands, reads,\n * results, SSE stream payloads, and frontend UI events.\n *\n * Identifier discipline: where a payload carries an annotation or\n * resource id, the TypeScript layer narrows the OpenAPI `string` to the\n * branded type (`AnnotationId`, `ResourceId`, `UserId`). The runtime\n * wire shape is unchanged (brands have no runtime representation);\n * what this buys us is that command handlers don't have to re-brand\n * at every seam. Brand once at the entry boundary (HTTP route handler,\n * DOM attribute read, URL param parse), not at every bus hop in\n * between. See `.plans/BRAND-UPSTREAM.md` for the rationale.\n *\n * Organized by flow (verb), then by category within each flow.\n */\n\nimport type { components } from './types';\nimport type { AnnotationId, ResourceId } from './identifiers';\nimport type { Annotation } from './annotation-types';\nimport type { ResourceDescriptor } from './graph';\nimport type { StoredEvent } from './event-base';\nimport type { EventOfType } from './persisted-events';\nimport type { AnchorRect } from './bus-ui-types';\n\n// Branded overrides for OpenAPI command payloads that carry identifier\n// fields. Narrows `string` → branded at the TypeScript layer.\n//\n// `_userId` is the gateway-injected authenticated DID (string at the\n// schema layer); handlers that need a `UserId` brand it locally.\ntype MarkDeleteCommand =\n components['schemas']['MarkDeleteCommand'] & {\n annotationId: AnnotationId;\n resourceId?: ResourceId;\n };\ntype MarkUpdateBodyCommand =\n components['schemas']['MarkUpdateBodyCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\ntype BindInitiateCommand =\n components['schemas']['BindInitiateCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\ntype BindUpdateBodyCommand =\n components['schemas']['BindUpdateBodyCommand'] & {\n annotationId: AnnotationId;\n resourceId: ResourceId;\n };\n\n/**\n * The unified EventMap — every channel on the EventBus.\n *\n * Convention:\n * - Domain events (past tense): StoredEvent<Interface> — branded types\n * - Commands/reads/results/UI: OpenAPI schema refs — plain strings\n * - void: UI-only signals with no payload\n */\n\n\nexport type EventMap = {\n\n // ========================================================================\n // YIELD FLOW — resource creation, update, move, clone\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'yield:created': StoredEvent<EventOfType<'yield:created'>>;\n 'yield:cloned': StoredEvent<EventOfType<'yield:cloned'>>;\n 'yield:updated': StoredEvent<EventOfType<'yield:updated'>>;\n 'yield:moved': StoredEvent<EventOfType<'yield:moved'>>;\n 'yield:representation-added': StoredEvent<EventOfType<'yield:representation-added'>>;\n 'yield:representation-removed': StoredEvent<EventOfType<'yield:representation-removed'>>;\n\n // Generation lifecycle flows through the unified job:* family\n // (job:start, job:report-progress, job:complete, job:fail). The\n // pre-unification `yield:progress`/`yield:finished`/`yield:failed`\n // channels were removed on the lifecycle-unification.\n\n // Commands\n 'yield:create': components['schemas']['YieldCreateCommand'];\n 'yield:update': components['schemas']['YieldUpdateCommand'];\n 'yield:mv': components['schemas']['YieldMvCommand'];\n 'yield:clone': void;\n 'yield:clone-token-requested': components['schemas']['YieldCloneTokenRequest'];\n 'yield:clone-resource-requested': components['schemas']['YieldCloneResourceRequest'];\n 'yield:clone-create': components['schemas']['YieldCloneCreateCommand'];\n\n // Command results\n 'yield:create-ok': components['schemas']['YieldCreateOk'];\n 'yield:create-failed': components['schemas']['CommandError'];\n 'yield:update-ok': components['schemas']['YieldUpdateOk'];\n 'yield:update-failed': components['schemas']['CommandError'];\n 'yield:move-failed': { fromUri: string } & components['schemas']['CommandError'];\n 'yield:clone-token-generated': { correlationId: string; response: components['schemas']['CloneResourceWithTokenResponse'] };\n 'yield:clone-token-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'yield:clone-resource-result': { correlationId: string; response: components['schemas']['GetResourceByTokenResponse'] };\n 'yield:clone-resource-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'yield:clone-created': components['schemas']['YieldCloneCreated'];\n 'yield:clone-create-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // ========================================================================\n // MARK FLOW — annotation CRUD, AI assist, resource lifecycle\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'mark:added': StoredEvent<EventOfType<'mark:added'>>;\n 'mark:removed': StoredEvent<EventOfType<'mark:removed'>>;\n 'mark:body-updated': StoredEvent<EventOfType<'mark:body-updated'>>;\n 'mark:entity-tag-added': StoredEvent<EventOfType<'mark:entity-tag-added'>>;\n 'mark:entity-tag-removed': StoredEvent<EventOfType<'mark:entity-tag-removed'>>;\n 'mark:archived': StoredEvent<EventOfType<'mark:archived'>>;\n 'mark:unarchived': StoredEvent<EventOfType<'mark:unarchived'>>;\n\n // Annotation-job lifecycle flows through the unified job:* family\n // (job:start, job:report-progress, job:complete, job:fail). UI\n // consumers filter by jobType. The pre-unification channels\n // `mark:progress`/`mark:assist-finished`/`mark:assist-failed` were\n // removed on the lifecycle-unification.\n\n // Commands\n 'mark:create-request': components['schemas']['MarkCreateRequest'];\n 'mark:create': components['schemas']['MarkCreateCommand'];\n 'mark:delete': MarkDeleteCommand;\n 'mark:update-body': MarkUpdateBodyCommand;\n 'mark:archive': components['schemas']['MarkArchiveCommand'];\n 'mark:unarchive': components['schemas']['MarkUnarchiveCommand'];\n 'mark:update-entity-types': components['schemas']['MarkUpdateEntityTypesCommand'];\n\n // Command results\n 'mark:create-ok': components['schemas']['MarkCreateOk'];\n 'mark:create-failed': components['schemas']['CommandError'];\n 'mark:delete-ok': components['schemas']['MarkDeleteOk'];\n 'mark:delete-failed': components['schemas']['CommandError'];\n // archive/unarchive confirmed-write replies (bridged) — correlation-keyed\n // acks the SDK's busRequest awaits. Failure routes the real outcome back\n // instead of the old fire-and-forget silence (.plans/bugs/BRIDGE-GAPS.md).\n 'mark:archive-ok': { correlationId?: string };\n 'mark:archive-failed': components['schemas']['CommandError'];\n 'mark:unarchive-ok': { correlationId?: string };\n 'mark:unarchive-failed': components['schemas']['CommandError'];\n // update-entity-types confirmed-write reply (bridged) — correlation-keyed ack\n // the SDK's busRequest awaits; failure routes the real outcome back rather than\n // the old fire-and-forget silence (.plans/bugs/BRIDGE-GAPS.md).\n 'mark:update-entity-types-ok': { correlationId?: string };\n 'mark:update-entity-types-failed': components['schemas']['CommandError'];\n 'mark:body-update-failed': components['schemas']['CommandError'];\n\n // UI events\n 'mark:select-comment': components['schemas']['SelectionData'];\n 'mark:select-tag': components['schemas']['SelectionData'];\n 'mark:select-assessment': components['schemas']['SelectionData'];\n 'mark:select-reference': components['schemas']['SelectionData'];\n 'mark:requested': components['schemas']['MarkRequestedEvent'];\n 'mark:cancel-pending': void;\n 'mark:submit': components['schemas']['MarkSubmitEvent'];\n 'mark:assist-request': components['schemas']['MarkAssistRequestEvent'];\n 'mark:progress-dismiss': void;\n // Client-local: the assist Observable went silent past its deadline (no\n // progress, no completion, no job:fail). Emitted by mark-state-unit so the\n // outcome-notification layer can tell the user; a real job failure arrives\n // as job:fail instead and never produces this.\n 'mark:assist-timeout': { resourceId: string; motivation: components['schemas']['Motivation'] };\n // Client-local UI notifications for annotation command failures, emitted by\n // the awaiting catch (mark-state-unit), which inherently knows whose command\n // failed on which resource. Distinct from the `mark:create-failed` /\n // `mark:delete-failed` wire replies above: those are busRequest correlation\n // plumbing (CommandError, matched by correlationId, bridged to every\n // client) and are NOT for UI consumption — subscribing to them raw\n // double-toasts the requester and leaks other users' failures.\n 'mark:create-error': { resourceId: string; message: string };\n 'mark:delete-error': { resourceId: string; message: string };\n // Same pattern for bind body updates initiated by callers that cannot toast\n // directly (e.g. ReferenceEntry's unlink); awaiting callers with their own\n // toast surface (the reference wizard) surface failures themselves instead.\n 'bind:body-error': { resourceId: string; message: string };\n\n // ========================================================================\n // FRAME FLOW — schema-layer vocabulary (entity types; future tag schemas,\n // relation/predicate types, ontology import). The eighth flow.\n // ========================================================================\n\n // Domain events (branded — system of record). System-level: no resourceId.\n 'frame:entity-type-added': StoredEvent<EventOfType<'frame:entity-type-added'>>;\n 'frame:tag-schema-added': StoredEvent<EventOfType<'frame:tag-schema-added'>>;\n\n // Commands\n 'frame:add-entity-type': components['schemas']['FrameAddEntityTypeCommand'];\n 'frame:add-tag-schema': components['schemas']['FrameAddTagSchemaCommand'];\n\n // Command results — `*-add-ok` / `*-add-failed` are correlation-keyed replies\n // for the SDK's confirmed `busRequest` writes (both bridged). In-process callers\n // (bootstrap/replay/import) instead race the `frame:*-added` domain event and\n // don't await `*-add-ok`, so its correlationId is optional.\n 'frame:entity-type-add-ok': { correlationId?: string };\n 'frame:entity-type-add-failed': components['schemas']['CommandError'];\n 'frame:tag-schema-add-ok': { correlationId?: string };\n 'frame:tag-schema-add-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // BIND FLOW — reference linking\n // ========================================================================\n\n 'bind:initiate': BindInitiateCommand;\n 'bind:update-body': BindUpdateBodyCommand;\n 'bind:body-updated': components['schemas']['BindBodyUpdated'];\n 'bind:body-update-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // MATCH FLOW — search\n // ========================================================================\n\n 'match:search-requested': components['schemas']['MatchSearchRequest'];\n 'match:search-results': components['schemas']['MatchSearchResult'];\n 'match:search-failed': components['schemas']['MatchSearchFailed'];\n\n // ========================================================================\n // GATHER FLOW — context gathering\n // ========================================================================\n\n 'gather:requested': components['schemas']['GatherAnnotationRequest'];\n 'gather:complete': components['schemas']['GatherAnnotationComplete'];\n 'gather:failed': { correlationId: string; annotationId: string } & components['schemas']['CommandError'];\n 'gather:resource-requested': components['schemas']['GatherResourceRequest'];\n 'gather:resource-complete': components['schemas']['GatherResourceComplete'];\n 'gather:resource-failed': { correlationId: string; resourceId: string } & components['schemas']['CommandError'];\n\n 'gather:summary-requested': components['schemas']['GatherSummaryRequest'];\n 'gather:summary-result': { correlationId: string; response: Record<string, unknown> };\n 'gather:summary-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // SSE stream payloads\n 'gather:annotation-progress': components['schemas']['GatherProgress'];\n\n // ========================================================================\n // BROWSE FLOW — knowledge base reads + UI navigation\n // ========================================================================\n\n // Reads.\n //\n // Reply `response` payloads carry DOMAIN-flavored documents: the KS serves\n // real, validated ids, so these declare the branded `Annotation` /\n // `ResourceDescriptor` (annotation-types.ts / graph.ts) rather than the raw\n // OpenAPI flavors — consumers must never need to re-brand (`as Annotation[]`)\n // what the protocol already guarantees. Field overrides via Omit +\n // intersection; envelope shape per .plans/REPLY-SHAPE-STANDARD.md.\n 'browse:resource-requested': components['schemas']['BrowseResourceRequest'];\n 'browse:resource-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetResourceResponse'], 'resource' | 'annotations' | 'entityReferences'> & {\n resource: ResourceDescriptor;\n annotations: Annotation[];\n entityReferences: Annotation[];\n };\n };\n 'browse:resource-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n // A resource's derived coordinate map — the text recovered from its bytes\n // plus the geometry that indexes it (ANCHORED-TEXT-CACHE Lane 5).\n //\n // Read-only over the wire: the Smelter is the sole producer and publishes\n // through `IContentTransport`, never over this channel. `null` in the reply\n // means no map has been derived, which is the common case and not an error.\n 'browse:anchored-text-requested': components['schemas']['BrowseAnchoredTextRequest'];\n 'browse:anchored-text-result': { correlationId: string; response: components['schemas']['ExtractionOutcome'] | null };\n 'browse:anchored-text-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:resources-requested': components['schemas']['BrowseResourcesRequest'];\n 'browse:resources-result': {\n correlationId: string;\n response: Omit<components['schemas']['ListResourcesResponse'], 'resources'> & {\n resources: ResourceDescriptor[];\n };\n };\n 'browse:resources-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotations-requested': components['schemas']['BrowseAnnotationsRequest'];\n 'browse:annotations-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetAnnotationsResponse'], 'annotations'> & {\n annotations: Annotation[];\n };\n };\n 'browse:annotations-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-requested': components['schemas']['BrowseAnnotationRequest'];\n 'browse:annotation-result': {\n correlationId: string;\n response: Omit<components['schemas']['GetAnnotationResponse'], 'annotation' | 'resource' | 'resolvedResource'> & {\n annotation: Annotation;\n resource: ResourceDescriptor | null;\n resolvedResource: ResourceDescriptor | null;\n };\n };\n 'browse:annotation-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:events-requested': components['schemas']['BrowseEventsRequest'];\n 'browse:events-result': components['schemas']['BrowseEventsResult'];\n 'browse:events-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-history-requested': components['schemas']['BrowseAnnotationHistoryRequest'];\n 'browse:annotation-history-result': components['schemas']['BrowseAnnotationHistoryResult'];\n 'browse:annotation-history-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:annotation-context-requested': components['schemas']['BrowseAnnotationContextRequest'];\n 'browse:annotation-context-result': { correlationId: string; response: Record<string, unknown> };\n 'browse:annotation-context-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:referenced-by-requested': components['schemas']['BrowseReferencedByRequest'];\n 'browse:referenced-by-result': components['schemas']['BrowseReferencedByResult'];\n 'browse:referenced-by-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:entity-types-requested': components['schemas']['BrowseEntityTypesRequest'];\n 'browse:entity-types-result': components['schemas']['BrowseEntityTypesResult'];\n 'browse:entity-types-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:tag-schemas-requested': components['schemas']['BrowseTagSchemasRequest'];\n 'browse:tag-schemas-result': components['schemas']['BrowseTagSchemasResult'];\n 'browse:tag-schemas-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:agents-requested': components['schemas']['BrowseAgentsRequest'];\n 'browse:agents-result': components['schemas']['BrowseAgentsResult'];\n 'browse:agents-failed': { correlationId: string } & components['schemas']['CommandError'];\n\n 'browse:directory-requested': components['schemas']['BrowseDirectoryRequest'];\n 'browse:directory-result': components['schemas']['BrowseDirectoryResult'];\n 'browse:directory-failed': { correlationId: string; path: string } & components['schemas']['CommandError'];\n\n // UI events (session-scoped — fire on the client bus, tied to a KB)\n 'browse:click': components['schemas']['BrowseClickEvent'] & { anchorRect?: AnchorRect };\n 'browse:resource-open': components['schemas']['BrowseResourceOpenEvent'];\n 'browse:resource-viewed': components['schemas']['BrowseResourceViewedEvent'];\n 'browse:entity-type-clicked': components['schemas']['BrowseEntityTypeClickedEvent'];\n\n // ========================================================================\n // SHELL — app-scoped UI events (fire on SemiontBrowser's bus, not the\n // per-session client bus). These must work regardless of whether a\n // KB session is active: panel toggles, sidebar, tab bar, routing.\n // ========================================================================\n\n 'panel:toggle': components['schemas']['BrowsePanelToggleEvent'];\n 'panel:open': components['schemas']['BrowsePanelOpenEvent'] & { anchorRect?: AnchorRect };\n 'panel:close': void;\n 'shell:sidebar-toggle': void;\n 'tabs:close': components['schemas']['BrowseResourceCloseEvent'];\n 'tabs:reorder': components['schemas']['BrowseResourceReorderEvent'];\n 'nav:link-clicked': components['schemas']['BrowseLinkClickedEvent'];\n 'nav:push': components['schemas']['BrowseRouterPushEvent'];\n 'nav:external': components['schemas']['BrowseExternalNavigateEvent'] & { cancelFallback: () => void };\n\n // ========================================================================\n // BECKON FLOW — annotation attention\n // ========================================================================\n\n 'beckon:hover': components['schemas']['BeckonHoverEvent'];\n 'beckon:focus': components['schemas']['BeckonFocusEvent'];\n 'beckon:sparkle': components['schemas']['BeckonSparkleEvent'];\n\n // ========================================================================\n // JOB FLOW — worker commands + domain events\n // ========================================================================\n\n // Domain events (branded — system of record)\n 'job:started': StoredEvent<EventOfType<'job:started'>>;\n 'job:completed': StoredEvent<EventOfType<'job:completed'>>;\n 'job:failed': StoredEvent<EventOfType<'job:failed'>>;\n\n // Commands\n 'job:start': components['schemas']['JobStartCommand'];\n 'job:report-progress': components['schemas']['JobReportProgressCommand'];\n 'job:complete': components['schemas']['JobCompleteCommand'];\n 'job:fail': components['schemas']['JobFailCommand'];\n 'job:queued': components['schemas']['JobQueuedEvent'];\n 'job:cancel-requested': components['schemas']['JobCancelRequest'];\n 'job:status-requested': components['schemas']['JobStatusRequest'];\n 'job:create': components['schemas']['JobCreateCommand'];\n 'job:claim': components['schemas']['JobClaimCommand'];\n\n // Results\n 'job:status-result': components['schemas']['JobStatusResult'];\n 'job:status-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'job:created': components['schemas']['JobCreatedResult'];\n 'job:create-failed': { correlationId: string } & components['schemas']['CommandError'];\n 'job:claimed': { correlationId: string; response: Record<string, unknown> };\n 'job:claim-failed': { correlationId: string } & components['schemas']['CommandError'];\n // cancel-by-type confirmed-write reply: the count of *pending* jobs cancelled\n // (running jobs finish — there's no worker-kill channel). Failure surfaces a\n // queue error instead of the old silent swallow (.plans/bugs/BRIDGE-GAPS.md).\n 'job:cancel-ok': { correlationId?: string; response: { cancelled: number } };\n 'job:cancel-failed': components['schemas']['CommandError'];\n\n // ========================================================================\n // WEAVE FLOW — graph projection progress (GRAPH-PROJECTION-SYNC, D2 = push)\n // ========================================================================\n\n /**\n * Emitted by the Weaver after applying an event (or a batch's last event)\n * for a resource to the graph. `sequenceNumber` is the resource-stream\n * sequence of the last applied event. Folded by `WeaveProgress`\n * (make-meaning) into the backend-local applied map that the\n * `whenApplied` barrier awaits. In-process signal today; crosses the\n * bus gateway after WEAVER-ISOLATION.\n */\n 'weave:applied': { resourceId: string; sequenceNumber: number };\n\n // Signal — the vector projection's per-resource decision report: emitted\n // by the Smelter after indexing a resource's content ('indexed') or after\n // deciding not to ('skipped', with a `reason` naming the decline — the\n // SMELTER-MEDIA-TYPES telemetry vocabulary: 'no-extractor' | 'empty' today,\n // the PDF decline classes when extraction lands). Keyed by the\n // checksum of the bytes inspected — \"settled at C\" is read-your-writes for\n // exactly that content. NEVER emitted on transient failures: an error is not\n // a decision (SMELTER-INDEX-SYNC A2). Consumed by the backend-local\n // `SmeltProgress` fold behind the gather-side barrier. This is the\n // Smelter's single outbound signal (SMELTER-AXIOMS D3, as amended).\n 'smelt:settled': { resourceId: string; contentChecksum: string; outcome: 'indexed' | 'skipped'; reason?: 'no-extractor' | 'empty' | 'no-text-layer' | 'encrypted' | 'corrupt' | 'too-large' };\n\n // Command — rebuild the graph projection from the event log (full when\n // resourceId is absent, one resource when present). Served by the Weaver;\n // replaces direct `rebuildAll()`/`rebuildResource()` access, which does\n // not survive the container split (WEAVER-ISOLATION D3). Correlated\n // request/reply via the BUS_OPERATIONS registry.\n 'weave:rebuild': components['schemas']['WeaveRebuildCommand'];\n 'weave:rebuild-ok': { correlationId?: string };\n 'weave:rebuild-failed': { correlationId?: string; message: string };\n\n // Command — rebuild anchored-text artifacts by re-running extraction\n // (every geometry-capable resource when resourceId is absent, one when\n // present). Served by the Smelter, serialized, never destructive, and\n // with ZERO embedding calls — only the derived map is re-made\n // (PERSIST-ANCHORS P0). Correlated request/reply via BUS_OPERATIONS.\n 'smelt:rebuild-anchors': components['schemas']['SmeltRebuildAnchorsCommand'];\n 'smelt:rebuild-anchors-ok': { correlationId?: string };\n 'smelt:rebuild-anchors-failed': { correlationId?: string; message: string };\n\n // ========================================================================\n // SETTINGS (frontend-only)\n // ========================================================================\n\n 'settings:theme-changed': components['schemas']['SettingsThemeChangedEvent'];\n 'settings:line-numbers-toggled': void;\n 'settings:locale-changed': components['schemas']['SettingsLocaleChangedEvent'];\n 'settings:hover-delay-changed': components['schemas']['SettingsHoverDelayChangedEvent'];\n\n // ========================================================================\n // SSE infrastructure\n // ========================================================================\n\n 'stream-connected': Record<string, never>;\n 'replay-window-exceeded': { resourceId?: string; lastEventId: number; missedCount: number; cap: number; message: string };\n /**\n * Emitted by the `/bus/subscribe` handler when a client reconnected\n * with `Last-Event-ID: p-<scope>-<seq>` but the server could not\n * replay all missed persisted events for that scope (retention\n * window exceeded, scope unknown, or request unparseable). The\n * client should treat this as a signal to fall back to the pre-\n * resumption contract: invalidate caches for the affected scope\n * and re-read from scratch. Analogous to `replay-window-exceeded`\n * but scoped to the bus gateway rather than the per-resource\n * events stream.\n *\n * `scope` is the scope string the client asked about (omitted for\n * global-persisted resumption gaps, if that path ever exists).\n * `reason` is human-readable, for logging.\n */\n 'bus:resume-gap': { scope?: string; lastSeenId?: string; reason: string };\n 'session:joined': components['schemas']['SessionJoinedEvent'];\n 'session:left': components['schemas']['SessionLeftEvent'];\n};\n\nexport type { AnchorRect } from './bus-ui-types';\n\n/**\n * Any valid channel name on the EventBus — `keyof EventMap`, the root channel\n * type. Two subsets matter, and confusing them is a silent-failure trap:\n *\n * - `EmittableChannel` (below) — channels with a non-null `CHANNEL_SCHEMAS`\n * entry; what you EMIT (the `/bus/emit` gateway validates the payload).\n * - `BridgedChannel` (`bridged-channels.ts`) — the transport fan-in set; the\n * only channels a client can SUBSCRIBE to over a concrete transport.\n *\n * Request/reply (`busRequest`) emits on an `EmittableChannel` and subscribes on\n * `BridgedChannel` replies. A reply channel that is a valid `EventName` but NOT\n * in `BRIDGED_CHANNELS` is never delivered → the request times out with no\n * compile or runtime error (see\n * `.plans/bugs/gather-resource-complete-not-bridged.md`). `busRequest` now types\n * its reply params `BridgedChannel` so that omission is a compile error.\n */\nexport type EventName = keyof EventMap;\n\n/**\n * Genuine resource-bound broadcast event types.\n *\n * Publishers emit these on the scoped EventBus (`eventBus.scope(resourceId)`)\n * because every participant viewing the resource should receive them — not\n * just the caller who triggered the originating action. Examples: resource\n * generation progress, which multiple viewers of a generating resource all\n * want to see.\n *\n * Non-broadcast progress (AI-assist progress for one user, search results\n * for one caller) does NOT belong here. Those are per-caller correlation-ID\n * responses and publish globally — the caller filters by `correlationId`.\n *\n * The SDK's resource-scoped `browse.*` live queries wire these channels —\n * subscribing acquires the scope via the transport's `subscribeToResource`\n * (`scope=id&scoped=<channel>`) so the SSE route delivers them to that\n * participant (freshness follows observation; #847). WorkerStateUnit uses this\n * list to decide which emitted events to scope to their resource.\n */\nexport const RESOURCE_BROADCAST_TYPES = [\n // Currently empty. `job:complete` / `job:fail` were moved to GLOBAL,\n // `jobId`-keyed correlation delivery (#847): the dispatching caller\n // filters by `jobId`, and resource viewers filter the same global stream\n // by `resourceId` — no resource-scoped copy, so a client that is both\n // dispatcher and viewer no longer receives it twice. This set remains as\n // the extension point for *genuine* resource-bound broadcasts — events\n // every viewer of a resource should see and no single caller owns (e.g.\n // resource-generation progress for multiple viewers).\n] as const satisfies readonly EventName[];\n\nexport type ResourceBroadcastType = typeof RESOURCE_BROADCAST_TYPES[number];\n\n/**\n * Authoritative map from bus channel to OpenAPI schema name.\n *\n * Every {@link EventName} must appear. The `satisfies` clause below\n * enforces completeness at compile time — adding a channel to\n * {@link EventMap} without adding an entry here is a build error.\n *\n * Values:\n * - `<SchemaName>`: payload validates against `components['schemas'][SchemaName]`.\n * - `null`: no single-schema validation. Used for branded\n * `StoredEvent` wrappers, `void` UI signals, and compound inline\n * types (e.g. `{ correlationId } & CommandError`). These are not\n * validated by `/bus/emit`.\n *\n * The `/bus/emit` route reads this map to validate incoming payloads.\n * Consumers can also use it to do client-side pre-flight validation\n * before emitting.\n */\nexport const CHANNEL_SCHEMAS = {\n // ── YIELD FLOW ──────────────────────────────────────────────────\n 'yield:created': null, // StoredEvent\n 'yield:cloned': null,\n 'yield:updated': null,\n 'yield:moved': null,\n 'yield:representation-added': null,\n 'yield:representation-removed': null,\n 'yield:create': 'YieldCreateCommand',\n 'yield:update': 'YieldUpdateCommand',\n 'yield:mv': 'YieldMvCommand',\n 'yield:clone': null, // void\n 'yield:clone-token-requested': 'YieldCloneTokenRequest',\n 'yield:clone-resource-requested': 'YieldCloneResourceRequest',\n 'yield:clone-create': 'YieldCloneCreateCommand',\n 'yield:create-ok': 'YieldCreateOk',\n 'yield:create-failed': 'CommandError',\n 'yield:update-ok': 'YieldUpdateOk',\n 'yield:update-failed': null, // { correlationId } & CommandError\n 'yield:move-failed': null, // { fromUri } & CommandError\n 'yield:clone-token-generated': null, // { correlationId; response: CloneResourceWithTokenResponse }\n 'yield:clone-token-failed': null, // { correlationId } & CommandError\n 'yield:clone-resource-result': null, // { correlationId; response: GetResourceByTokenResponse }\n 'yield:clone-resource-failed': null, // { correlationId } & CommandError\n 'yield:clone-created': 'YieldCloneCreated',\n 'yield:clone-create-failed': null, // { correlationId } & CommandError\n\n // ── MARK FLOW ───────────────────────────────────────────────────\n 'mark:added': null, // StoredEvent\n 'mark:removed': null,\n 'mark:body-updated': null,\n 'mark:entity-tag-added': null,\n 'mark:entity-tag-removed': null,\n 'frame:entity-type-added': null,\n 'frame:tag-schema-added': null,\n 'mark:archived': null,\n 'mark:unarchived': null,\n 'mark:create-request': 'MarkCreateRequest',\n 'mark:create': 'MarkCreateCommand',\n 'mark:delete': 'MarkDeleteCommand',\n 'mark:update-body': 'MarkUpdateBodyCommand',\n 'mark:archive': 'MarkArchiveCommand',\n 'mark:unarchive': 'MarkUnarchiveCommand',\n 'mark:update-entity-types': 'MarkUpdateEntityTypesCommand',\n 'frame:add-entity-type': 'FrameAddEntityTypeCommand',\n 'frame:add-tag-schema': 'FrameAddTagSchemaCommand',\n 'mark:create-ok': 'MarkCreateOk',\n 'mark:create-failed': 'CommandError',\n 'mark:delete-ok': 'MarkDeleteOk',\n 'mark:delete-failed': 'CommandError',\n 'mark:archive-ok': null,\n 'mark:archive-failed': 'CommandError',\n 'mark:unarchive-ok': null,\n 'mark:unarchive-failed': 'CommandError',\n 'mark:update-entity-types-ok': null,\n 'mark:update-entity-types-failed': 'CommandError',\n 'mark:body-update-failed': 'CommandError',\n 'frame:entity-type-add-ok': null,\n 'frame:entity-type-add-failed': 'CommandError',\n 'frame:tag-schema-add-ok': null,\n 'frame:tag-schema-add-failed': 'CommandError',\n 'mark:select-comment': 'SelectionData',\n 'mark:select-tag': 'SelectionData',\n 'mark:select-assessment': 'SelectionData',\n 'mark:select-reference': 'SelectionData',\n 'mark:requested': 'MarkRequestedEvent',\n 'mark:cancel-pending': null, // void\n 'mark:submit': 'MarkSubmitEvent',\n 'mark:assist-request': 'MarkAssistRequestEvent',\n 'mark:progress-dismiss': null, // void\n 'mark:assist-timeout': null, // { resourceId; motivation } — client-local UI signal\n 'mark:create-error': null, // { resourceId; message } — client-local UI signal\n 'mark:delete-error': null, // { resourceId; message } — client-local UI signal\n 'bind:body-error': null, // { resourceId; message } — client-local UI signal\n\n // ── BIND FLOW ───────────────────────────────────────────────────\n 'bind:initiate': 'BindInitiateCommand',\n 'bind:update-body': 'BindUpdateBodyCommand',\n 'bind:body-updated': 'BindBodyUpdated',\n 'bind:body-update-failed': 'CommandError',\n\n // ── MATCH FLOW ──────────────────────────────────────────────────\n 'match:search-requested': 'MatchSearchRequest',\n 'match:search-results': 'MatchSearchResult',\n 'match:search-failed': 'MatchSearchFailed',\n\n // ── GATHER FLOW ─────────────────────────────────────────────────\n 'gather:requested': 'GatherAnnotationRequest',\n 'gather:complete': 'GatherAnnotationComplete',\n 'gather:failed': null, // { correlationId; annotationId } & CommandError\n 'gather:resource-requested': 'GatherResourceRequest',\n 'gather:resource-complete': 'GatherResourceComplete',\n 'gather:resource-failed': null, // { correlationId; resourceId } & CommandError\n 'gather:summary-requested': 'GatherSummaryRequest',\n 'gather:summary-result': null, // { correlationId; response: Record<string, unknown> }\n 'gather:summary-failed': null, // { correlationId } & CommandError\n 'gather:annotation-progress': 'GatherProgress',\n\n // ── BROWSE FLOW ─────────────────────────────────────────────────\n 'browse:resource-requested': 'BrowseResourceRequest',\n 'browse:resource-result': 'BrowseResourceResult',\n 'browse:resource-failed': null, // { correlationId } & CommandError\n 'browse:anchored-text-requested': 'BrowseAnchoredTextRequest',\n 'browse:anchored-text-result': 'BrowseAnchoredTextResult',\n 'browse:anchored-text-failed': null, // { correlationId } & CommandError\n 'browse:resources-requested': 'BrowseResourcesRequest',\n 'browse:resources-result': 'BrowseResourcesResult',\n 'browse:resources-failed': null,\n 'browse:annotations-requested': 'BrowseAnnotationsRequest',\n 'browse:annotations-result': 'BrowseAnnotationsResult',\n 'browse:annotations-failed': null,\n 'browse:annotation-requested': 'BrowseAnnotationRequest',\n 'browse:annotation-result': 'BrowseAnnotationResult',\n 'browse:annotation-failed': null,\n 'browse:events-requested': 'BrowseEventsRequest',\n 'browse:events-result': 'BrowseEventsResult',\n 'browse:events-failed': null,\n 'browse:annotation-history-requested': 'BrowseAnnotationHistoryRequest',\n 'browse:annotation-history-result': 'BrowseAnnotationHistoryResult',\n 'browse:annotation-history-failed': null,\n 'browse:annotation-context-requested': 'BrowseAnnotationContextRequest',\n 'browse:annotation-context-result': null, // { correlationId; response: Record<string, unknown> }\n 'browse:annotation-context-failed': null,\n 'browse:referenced-by-requested': 'BrowseReferencedByRequest',\n 'browse:referenced-by-result': 'BrowseReferencedByResult',\n 'browse:referenced-by-failed': null,\n 'browse:entity-types-requested': 'BrowseEntityTypesRequest',\n 'browse:entity-types-result': 'BrowseEntityTypesResult',\n 'browse:entity-types-failed': null,\n 'browse:tag-schemas-requested': 'BrowseTagSchemasRequest',\n 'browse:tag-schemas-result': 'BrowseTagSchemasResult',\n 'browse:tag-schemas-failed': null,\n 'browse:agents-requested': 'BrowseAgentsRequest',\n 'browse:agents-result': 'BrowseAgentsResult',\n 'browse:agents-failed': null,\n 'browse:directory-requested': 'BrowseDirectoryRequest',\n 'browse:directory-result': 'BrowseDirectoryResult',\n 'browse:directory-failed': null, // { correlationId; path } & CommandError\n 'browse:click': 'BrowseClickEvent', // includes runtime `anchorRect?: AnchorRect`\n 'browse:resource-open': 'BrowseResourceOpenEvent',\n 'browse:resource-viewed': 'BrowseResourceViewedEvent',\n 'browse:entity-type-clicked': 'BrowseEntityTypeClickedEvent',\n\n // ── SHELL (app-scoped UI events, fire on SemiontBrowser bus) ────\n 'panel:toggle': 'BrowsePanelToggleEvent',\n 'panel:open': null, // includes runtime `anchorRect?: AnchorRect`\n 'panel:close': null, // void\n 'shell:sidebar-toggle': null, // void\n 'tabs:close': 'BrowseResourceCloseEvent',\n 'tabs:reorder': 'BrowseResourceReorderEvent',\n 'nav:link-clicked': 'BrowseLinkClickedEvent',\n 'nav:push': 'BrowseRouterPushEvent',\n 'nav:external': null, // includes runtime `cancelFallback: () => void`\n\n // ── BECKON FLOW ─────────────────────────────────────────────────\n 'beckon:hover': 'BeckonHoverEvent',\n 'beckon:focus': 'BeckonFocusEvent',\n 'beckon:sparkle': 'BeckonSparkleEvent',\n\n // ── JOB FLOW ────────────────────────────────────────────────────\n 'job:started': null, // StoredEvent\n 'job:completed': null,\n 'job:failed': null,\n 'job:start': 'JobStartCommand',\n 'job:report-progress': 'JobReportProgressCommand',\n 'job:complete': 'JobCompleteCommand',\n 'job:fail': 'JobFailCommand',\n 'job:queued': 'JobQueuedEvent',\n 'job:cancel-requested': 'JobCancelRequest',\n 'job:status-requested': 'JobStatusRequest',\n 'job:create': 'JobCreateCommand',\n 'job:claim': 'JobClaimCommand',\n 'job:status-result': 'JobStatusResult',\n 'job:status-failed': null, // { correlationId } & CommandError\n 'job:created': 'JobCreatedResult',\n 'job:create-failed': null,\n 'job:claimed': null, // { correlationId; response: Record<string, unknown> }\n 'job:claim-failed': null,\n 'job:cancel-ok': null,\n 'job:cancel-failed': 'CommandError',\n\n // ── SETTINGS (frontend-only) ────────────────────────────────────\n 'settings:theme-changed': 'SettingsThemeChangedEvent',\n 'settings:line-numbers-toggled': null, // void\n 'settings:locale-changed': 'SettingsLocaleChangedEvent',\n 'settings:hover-delay-changed': 'SettingsHoverDelayChangedEvent',\n\n // ── WEAVE FLOW ──────────────────────────────────────────────────\n 'weave:applied': null, // { resourceId; sequenceNumber }\n 'smelt:settled': null, // { resourceId; contentChecksum; outcome; reason? }\n 'weave:rebuild': 'WeaveRebuildCommand',\n 'weave:rebuild-ok': null, // { correlationId }\n 'weave:rebuild-failed': null, // { correlationId; message }\n 'smelt:rebuild-anchors': 'SmeltRebuildAnchorsCommand',\n 'smelt:rebuild-anchors-ok': null, // { correlationId }\n 'smelt:rebuild-anchors-failed': null, // { correlationId; message }\n\n // ── SSE infrastructure ──────────────────────────────────────────\n 'stream-connected': null, // Record<string, never>\n 'replay-window-exceeded': null, // inline payload\n 'bus:resume-gap': null, // inline payload\n 'session:joined': 'SessionJoinedEvent',\n 'session:left': 'SessionLeftEvent',\n} as const satisfies Record<EventName, keyof components['schemas'] | null>;\n\n/** Channels where `/bus/emit` validates the payload (non-null schema). */\nexport type EmittableChannel = {\n [K in EventName]: typeof CHANNEL_SCHEMAS[K] extends null ? never : K\n}[EventName];\n","/**\n * Event Type Guards and Extraction Utilities\n *\n * Domain logic for working with resource events.\n * No React dependencies - safe to use in any JavaScript environment.\n */\n\nimport type { StoredEvent } from './event-base';\nimport type { AnnotationUri } from './branded-types';\n\n/**\n * Minimal event shape accepted by event utility functions.\n * Compatible with both the internal `StoredEvent` type and the OpenAPI-derived\n * schema type (`GetEventsResponse['events'][number]`), which lacks `version`.\n *\n * Flat shape — event fields and metadata are peers (no `event` wrapper).\n */\nexport interface StoredEventLike {\n id: string;\n type: string; // Intentionally loose — accepts OpenAPI-derived types where type is string\n timestamp: string;\n userId: string;\n resourceId?: string;\n payload?: unknown;\n metadata: {\n sequenceNumber: number;\n };\n}\n\n// =============================================================================\n// EVENT TYPE GUARDS AND EXTRACTION\n// =============================================================================\n\n/**\n * Extract annotation ID from event payload\n * Returns null if event is not annotation-related\n *\n * For mark:added: extracts full URI from payload.annotation.id\n * For mark:removed/mark:body-updated: constructs full URI from payload.annotationId (UUID) + resourceId\n */\nexport function getAnnotationUriFromEvent(event: StoredEventLike): AnnotationUri | null {\n const payload = event.payload as Record<string, any> | undefined;\n\n if (event.type === 'mark:added') {\n return payload?.annotation?.id as AnnotationUri || null;\n }\n\n if (event.type === 'mark:removed' || event.type === 'mark:body-updated') {\n if (payload?.annotationId && event.resourceId) {\n try {\n const resourceUri = event.resourceId;\n const baseUrl = resourceUri.substring(0, resourceUri.lastIndexOf('/resources/'));\n return `${baseUrl}/annotations/${payload.annotationId}` as AnnotationUri;\n } catch (e) {\n return null;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Check if an event is related to a specific annotation\n */\nexport function isEventRelatedToAnnotation(event: StoredEventLike, annotationUri: AnnotationUri): boolean {\n const eventAnnotationUri = getAnnotationUriFromEvent(event);\n return eventAnnotationUri === annotationUri;\n}\n\n/**\n * Type guard to check if an object is a StoredEvent (flat shape)\n */\nexport function isStoredEvent(event: any): event is StoredEvent {\n return event &&\n typeof event.id === 'string' &&\n typeof event.timestamp === 'string' &&\n typeof event.type === 'string' &&\n typeof event.metadata === 'object' &&\n typeof event.metadata.sequenceNumber === 'number';\n}\n\n","/**\n * Adaptive burst buffer RxJS operator.\n *\n * Passes the first event through immediately (zero latency for interactive use).\n * If more events arrive within the burst window, switches to accumulate mode\n * and flushes batches. Returns to passthrough mode after an idle period.\n *\n * Emits individual items (T) in passthrough mode and arrays (T[]) in batch mode.\n * Consumers distinguish via Array.isArray().\n *\n * Threshold tuning:\n * burstWindowMs — How long to wait for more events before flushing a batch.\n * 50ms is a good default: longer than event-loop jitter (~1-5ms)\n * but short enough to feel responsive.\n * maxBatchSize — Force-flush at this size to bound memory. 500 is safe for\n * Neo4j UNWIND queries. Increase if graph writes are cheap.\n * idleTimeoutMs — How long after the last flush before returning to passthrough.\n * 200ms is a good default. Must be >= burstWindowMs.\n *\n * See: packages/graph/docs/ARCHITECTURE.md for Weaver context.\n */\n\nimport { Observable, OperatorFunction } from 'rxjs';\n\nexport interface BurstBufferOptions {\n /**\n * Time window (ms) to detect burst activity after an event.\n * If another event arrives within this window, it is buffered.\n * The buffer flushes when no new event arrives for this duration (debounce).\n *\n * Recommended: 50ms.\n */\n burstWindowMs: number;\n\n /**\n * Maximum events to accumulate before forcing a flush.\n * Prevents unbounded memory growth during sustained bursts.\n *\n * Recommended: 500.\n */\n maxBatchSize: number;\n\n /**\n * Time (ms) of silence after the last flush before returning to passthrough mode.\n * The next event after this timeout emits immediately (leading edge).\n * Must be >= burstWindowMs.\n *\n * Recommended: 200ms.\n */\n idleTimeoutMs: number;\n}\n\n/**\n * Adaptive burst buffer operator.\n *\n * State machine:\n * PASSTHROUGH → event arrives → emit immediately, transition to ACCUMULATING\n * ACCUMULATING → event arrives → buffer it, reset burst timer\n * ACCUMULATING → burst timer fires (no new events for burstWindowMs) → flush buffer as T[]\n * ACCUMULATING → buffer reaches maxBatchSize → flush buffer as T[]\n * After flush → idle timer starts\n * Idle timer fires (no new events for idleTimeoutMs) → transition to PASSTHROUGH\n */\nexport function burstBuffer<T>(\n options: BurstBufferOptions\n): OperatorFunction<T, T | T[]> {\n const { burstWindowMs, maxBatchSize, idleTimeoutMs } = options;\n\n return (source: Observable<T>) =>\n new Observable<T | T[]>((subscriber) => {\n let mode: 'passthrough' | 'accumulating' = 'passthrough';\n let buffer: T[] = [];\n let burstTimer: ReturnType<typeof setTimeout> | null = null;\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n\n function clearBurstTimer() {\n if (burstTimer !== null) {\n clearTimeout(burstTimer);\n burstTimer = null;\n }\n }\n\n function clearIdleTimer() {\n if (idleTimer !== null) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n }\n\n function flush() {\n if (buffer.length === 0) return;\n const batch = buffer;\n buffer = [];\n subscriber.next(batch);\n }\n\n function startIdleTimer() {\n clearIdleTimer();\n idleTimer = setTimeout(() => {\n idleTimer = null;\n mode = 'passthrough';\n }, idleTimeoutMs);\n }\n\n const subscription = source.subscribe({\n next(value: T) {\n clearIdleTimer();\n\n if (mode === 'passthrough') {\n // Leading edge: emit immediately\n subscriber.next(value);\n // Transition to accumulating — next event within burstWindowMs gets buffered\n mode = 'accumulating';\n // Start a burst timer: if nothing else arrives, start idle countdown\n burstTimer = setTimeout(() => {\n burstTimer = null;\n flush(); // flush anything accumulated (normally empty at this point)\n startIdleTimer();\n }, burstWindowMs);\n return;\n }\n\n // mode === 'accumulating'\n buffer.push(value);\n\n // Reset the burst window timer (debounce pattern)\n clearBurstTimer();\n\n if (buffer.length >= maxBatchSize) {\n // Force flush at max batch size\n flush();\n startIdleTimer();\n } else {\n // Debounce: flush after burstWindowMs of silence\n burstTimer = setTimeout(() => {\n burstTimer = null;\n flush();\n startIdleTimer();\n }, burstWindowMs);\n }\n },\n\n error(err) {\n clearBurstTimer();\n clearIdleTimer();\n flush();\n subscriber.error(err);\n },\n\n complete() {\n clearBurstTimer();\n clearIdleTimer();\n flush();\n subscriber.complete();\n },\n });\n\n // Teardown: clean up timers and unsubscribe from source\n return () => {\n clearBurstTimer();\n clearIdleTimer();\n subscription.unsubscribe();\n };\n });\n}\n","/**\n * serializePerKey — run async work serialized per key, parallel across keys.\n *\n * Invariant: two calls with the same `key` run strictly in sequence (the\n * second `work` does not start until the first has settled). Calls with\n * different keys overlap freely.\n *\n * Error isolation: a rejected work function does not poison subsequent\n * tasks for the same key. The next task starts fresh from whatever state\n * the failed task left behind. The rejection still propagates to *this*\n * caller.\n *\n * Registry cleanup: the entry for a key is removed as soon as its chain\n * empties, so the Map stays bounded by the number of keys with work\n * currently in flight, not by the total number of keys ever seen.\n *\n * ## Usage\n *\n * ```ts\n * const chains = new Map<string, Promise<void>>();\n *\n * async function write(resourceId: string, event: Event) {\n * return serializePerKey(resourceId, chains, async () => {\n * // Read-modify-write on a view file. Any two concurrent calls with\n * // the same resourceId will be serialized; different resourceIds\n * // will proceed in parallel.\n * const view = await viewStorage.get(resourceId);\n * applyEvent(view, event);\n * await viewStorage.save(resourceId, view);\n * });\n * }\n * ```\n *\n * ## When to use this vs RxJS `groupBy + concatMap`\n *\n * Use `serializePerKey` when the work arrives as **direct method calls**\n * that need to block the caller until completion. This is the RPC shape\n * — think `EventStore.appendEvent` calling `await views.materializeResource(...)`\n * and needing the view written before any subscriber sees the published\n * event.\n *\n * Use RxJS `groupBy(keyFn) + concatMap(...)` when the work arrives as an\n * **event stream** that a component subscribes to once at startup. This\n * is how `Smelter`, `Weaver`, and `Gatherer` serialize their own\n * per-resource work — see their implementations in `packages/make-meaning`.\n *\n * Both patterns solve the same logical problem (\"serialize work per key\").\n * The choice is dictated by whether the caller is awaiting the result.\n */\nexport async function serializePerKey<K, T>(\n key: K,\n chains: Map<K, Promise<void>>,\n work: () => Promise<T>,\n): Promise<T> {\n const prev = chains.get(key) ?? Promise.resolve();\n\n // Chain onto prev, swallowing any error from the previous link so one\n // bad task doesn't poison subsequent ones for the same key. The new\n // link's own errors still propagate to our caller via `await next`.\n let result: T;\n const next = prev\n .catch(() => { /* prior failure doesn't block us */ })\n .then(async () => {\n result = await work();\n });\n\n chains.set(key, next);\n\n try {\n await next;\n return result!;\n } finally {\n // Only clear the entry if we're still the tail. If another caller\n // has already chained onto us, leave it so the chain stays intact.\n if (chains.get(key) === next) {\n chains.delete(key);\n }\n }\n}\n","/**\n * Logger interface for observability\n *\n * This interface is intentionally framework-agnostic to work with any logger\n * (winston, pino, bunyan, or simple console).\n *\n * Example usage:\n * ```typescript\n * import winston from 'winston';\n *\n * const logger = winston.createLogger({\n * level: 'debug',\n * transports: [new winston.transports.Console()]\n * });\n *\n * const service = new MyService(logger);\n * ```\n */\nexport interface Logger {\n debug(message: string, meta?: any): void;\n info(message: string, meta?: any): void;\n warn(message: string, meta?: any): void;\n error(message: string, meta?: any): void;\n child(meta: Record<string, any>): Logger;\n}\n\n/**\n * Serialize an error value into a form that JSON.stringify can handle\n * meaningfully.\n *\n * Winston's default JSON formatter serializes `Error` instances as `{}`\n * because `message`, `stack`, and `name` are non-enumerable properties on\n * the Error prototype. That means `logger.error('x', { error })` with a\n * raw Error argument produces useless log lines like\n * `{\"error\":{},\"message\":\"x\",...}`, throwing away the information you\n * actually need to diagnose the failure.\n *\n * This helper extracts the parts you want to see in a log — name,\n * message, stack, and cause — and leaves non-Error values alone (so\n * strings, numbers, and plain objects pass through unchanged).\n *\n * ## Usage\n *\n * ```ts\n * try {\n * await doSomething();\n * } catch (error) {\n * logger.error('Something failed', { error: errField(error) });\n * }\n * ```\n *\n * Use this at every `logger.error` call site that includes an `error`\n * field derived from a catch block. Raw `{ error }` without this helper\n * is almost always a bug.\n */\nexport function errField(error: unknown): unknown {\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n ...(error.cause !== undefined && { cause: errField(error.cause) }),\n };\n }\n return error;\n}\n","/**\n * Annotation body utilities\n *\n * These are the matcher primitives used by the `mark:body-updated` event\n * replay path (ViewMaterializer and Weaver) to apply add/remove/\n * replace operations against an annotation body.\n */\n\nimport type { components } from './types';\nimport type { Annotation } from './annotation-types';\n\ntype BodyPurpose = components['schemas']['BodyPurpose'];\n\n/**\n * Identity of a body item for matching purposes.\n *\n * Identity is `type + source` for SpecificResource and `type + value` for\n * TextualBody. `purpose` is OPTIONAL: if the caller provides it, it's\n * included in the match (used to disambiguate same-source bodies under\n * different purposes, per the W3C Web Annotation model). If the caller\n * omits it, the matcher ignores purpose and matches on identity alone.\n *\n * Callers SHOULD provide `purpose` when they know it (e.g., the bind flow\n * always unlinks a `purpose: 'linking'` body) so that future multi-purpose\n * annotations continue to disambiguate correctly. Leaving `purpose`\n * unspecified matches whichever purpose comes first in the body — which is\n * fine today because Semiont annotations currently have at most one body\n * item per (type, source/value) pair.\n */\nexport type BodyItemIdentity =\n | { type: 'SpecificResource'; source: string; purpose?: BodyPurpose }\n | { type: 'TextualBody'; value: string; purpose?: BodyPurpose };\n\n/**\n * Find a body item by identity. Returns the index of the first match, or -1.\n *\n * See `BodyItemIdentity` for matching semantics.\n */\nexport function findBodyItem(\n body: Annotation['body'],\n identity: BodyItemIdentity,\n): number {\n if (!Array.isArray(body)) {\n return -1;\n }\n\n for (let i = 0; i < body.length; i++) {\n const item = body[i];\n\n if (typeof item !== 'object' || item === null || !('type' in item)) {\n continue;\n }\n\n const itemType = (item as { type: unknown }).type;\n if (itemType !== identity.type) {\n continue;\n }\n\n // Identity field match (source or value)\n if (identity.type === 'SpecificResource') {\n if (!('source' in item)) continue;\n const itemSource = (item as { source: unknown }).source;\n if (itemSource !== identity.source) continue;\n } else {\n if (!('value' in item)) continue;\n const itemValue = (item as { value: unknown }).value;\n if (itemValue !== identity.value) continue;\n }\n\n // Purpose match — ONLY if the caller specified one. Omitted purpose\n // means \"any purpose on this identity\", which is what the bind-flow\n // unlinker wants today.\n if (identity.purpose !== undefined) {\n const itemPurpose = (item as { purpose?: unknown }).purpose;\n if (itemPurpose !== identity.purpose) continue;\n }\n\n return i;\n }\n\n return -1;\n}\n","/**\n * ID generation utilities.\n *\n * Built on `crypto.getRandomValues()`, NOT `crypto.randomUUID()`: browsers\n * expose `randomUUID` only in secure contexts (https, `http://localhost`,\n * `http://127.0.0.1`), so a page served over plain http from any other host\n * has no `randomUUID` and calling it throws — which broke the frontend from\n * the host-gateway IP (.plans/bugs/crypto-randomuuid-insecure-context.md).\n * `getRandomValues` is cryptographically sound and available in ALL contexts,\n * Node and browser, secure or not.\n */\n\n// Declared here because the core package tsconfig uses lib:ES2022 (no dom types).\ndeclare const crypto: { getRandomValues<T extends ArrayBufferView>(array: T): T };\n\nfunction v4Bytes(): Uint8Array {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8]! & 0x3f) | 0x80; // variant 10xx\n return bytes;\n}\n\nfunction hex(bytes: Uint8Array): string {\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/**\n * Generate a UUID v4 string WITHOUT dashes (32 hex chars).\n *\n * The dashless form is data shape: persisted annotation/resource/job ids are\n * built from it and land in URIs. Do not change the format.\n */\nexport function generateUuid(): string {\n return hex(v4Bytes());\n}\n\n/**\n * Generate a canonical dashed UUID v4 (36 chars, 8-4-4-4-12) — the format\n * `crypto.randomUUID()` produces, without its secure-context requirement.\n *\n * Use for ephemeral wire ids (`correlationId`s and the like).\n */\nexport function uuidV4(): string {\n const h = hex(v4Bytes());\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;\n}\n","/**\n * Annotation Assembly\n *\n * Pure functions for building W3C Annotations and applying body operations.\n * No EventBus, no persistence — just data transformation.\n */\n\nimport type { components } from './types';\nimport type { Selector } from './payload-types';\nimport type { Annotation } from './annotation-types';\nimport { annotationId } from './identifiers';\nimport { generateUuid } from './id-generation';\n\ntype Agent = components['schemas']['Agent'];\ntype AnnotationBody = components['schemas']['AnnotationBody'];\ntype CreateAnnotationRequest = components['schemas']['CreateAnnotationRequest'];\ntype UpdateAnnotationBodyRequest = components['schemas']['UpdateAnnotationBodyRequest'];\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\n\nexport interface AssembledAnnotation {\n annotation: Annotation;\n bodyArray: AnnotationBody[];\n}\n\n// =============================================================================\n// Selector utilities used by assembleAnnotation\n// =============================================================================\n\n/**\n * Get TextPositionSelector from a selector (single or array)\n */\nexport function getTextPositionSelector(selector: Selector | Selector[] | undefined): TextPositionSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextPositionSelector');\n if (!found) return null;\n return found.type === 'TextPositionSelector' ? found : null;\n}\n\n/**\n * Get SvgSelector from a selector (single or array)\n */\nexport function getSvgSelector(selector: Selector | Selector[] | undefined): SvgSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'SvgSelector');\n if (!found) return null;\n return found.type === 'SvgSelector' ? found : null;\n}\n\n/**\n * Get FragmentSelector from a selector (single or array)\n */\nexport function getFragmentSelector(selector: Selector | Selector[] | undefined): FragmentSelector | null {\n if (!selector) return null;\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'FragmentSelector');\n if (!found) return null;\n return found.type === 'FragmentSelector' ? found : null;\n}\n\n/**\n * Validate SVG markup for W3C compliance\n *\n * @returns null if valid, error message if invalid\n */\nexport function validateSvgMarkup(svg: string): string | null {\n if (!svg.includes('xmlns=\"http://www.w3.org/2000/svg\"')) {\n return 'SVG must include xmlns=\"http://www.w3.org/2000/svg\" attribute';\n }\n\n if (!svg.includes('<svg') || !svg.includes('</svg>')) {\n return 'SVG must have opening and closing tags';\n }\n\n const shapeElements = ['rect', 'circle', 'ellipse', 'polygon', 'polyline', 'path', 'line'];\n const hasShape = shapeElements.some(shape =>\n svg.includes(`<${shape}`) || svg.includes(`<${shape} `)\n );\n\n if (!hasShape) {\n return 'SVG must contain at least one shape element (rect, circle, ellipse, polygon, polyline, path, or line)';\n }\n\n return null;\n}\n\n// =============================================================================\n// Annotation assembly\n// =============================================================================\n\n/**\n * Build a complete W3C Annotation from a CreateAnnotationRequest.\n *\n * Generates a bare annotation ID (no URL prefix). URIs are constructed\n * at the API boundary when returning responses to clients.\n *\n * Throws on invalid input (missing motivation, invalid SVG markup). The target\n * selector is OPTIONAL — a source-only target annotates the whole resource (W3C;\n * e.g. resource-level edges), per RESOURCE-LEVEL-ANCHOR.\n */\nexport function assembleAnnotation(\n request: CreateAnnotationRequest,\n creator: Agent,\n): AssembledAnnotation {\n const newAnnotationId = annotationId(generateUuid());\n\n // The target selector is OPTIONAL — a source-only target annotates the whole\n // resource (W3C; e.g. resource-level edges). When an SvgSelector IS present,\n // its markup must still be valid.\n const svgSelector = getSvgSelector(request.target.selector);\n if (svgSelector) {\n const svgError = validateSvgMarkup(svgSelector.value);\n if (svgError) {\n throw new Error(`Invalid SVG markup: ${svgError}`);\n }\n }\n\n if (!request.motivation) {\n throw new Error('motivation is required');\n }\n\n const now = new Date().toISOString();\n const annotation: Annotation = {\n '@context': 'http://www.w3.org/ns/anno.jsonld' as const,\n 'type': 'Annotation' as const,\n id: newAnnotationId,\n motivation: request.motivation,\n target: request.target,\n body: request.body as Annotation['body'],\n creator,\n created: now,\n modified: now,\n };\n\n const bodyArray = (Array.isArray(request.body) ? request.body : request.body ? [request.body] : []) as AnnotationBody[];\n\n return { annotation, bodyArray };\n}\n\n/**\n * Apply body operations (add/remove/replace) to an annotation's body array.\n * Returns a new array — does not mutate the input.\n */\nexport function applyBodyOperations(\n body: Annotation['body'],\n operations: UpdateAnnotationBodyRequest['operations'],\n): AnnotationBody[] {\n const bodyArray = Array.isArray(body) ? [...body] : [];\n\n for (const op of operations) {\n if (op.op === 'add') {\n const exists = bodyArray.some(item =>\n JSON.stringify(item) === JSON.stringify(op.item)\n );\n if (!exists) {\n bodyArray.push(op.item);\n }\n } else if (op.op === 'remove') {\n const index = bodyArray.findIndex(item =>\n JSON.stringify(item) === JSON.stringify(op.item)\n );\n if (index !== -1) {\n bodyArray.splice(index, 1);\n }\n } else if (op.op === 'replace') {\n const index = bodyArray.findIndex(item =>\n JSON.stringify(item) === JSON.stringify(op.oldItem)\n );\n if (index !== -1) {\n bodyArray[index] = op.newItem;\n }\n }\n }\n\n return bodyArray;\n}\n","/**\n * Annotation and Selector Utilities\n *\n * Pure TypeScript utilities for working with W3C Web Annotations.\n * No React dependencies - safe to use in any JavaScript environment.\n *\n * Body is either empty array (stub) or single SpecificResource (resolved)\n * Body can be array of TextualBody (tagging) + SpecificResource (linking)\n * Target can be simple string IRI or object with source and optional selector\n */\n\nimport type { components } from './types';\nimport type { Selector } from './payload-types';\nimport type { Annotation } from './annotation-types';\n\n// Re-export selector utilities (canonical location is annotation-assembly)\nexport {\n getTextPositionSelector,\n getSvgSelector,\n getFragmentSelector,\n validateSvgMarkup,\n} from './annotation-assembly';\ntype HighlightAnnotation = Annotation;\ntype ReferenceAnnotation = Annotation;\ntype TextPositionSelector = components['schemas']['TextPositionSelector'];\ntype TextQuoteSelector = components['schemas']['TextQuoteSelector'];\ntype SvgSelector = components['schemas']['SvgSelector'];\ntype FragmentSelector = components['schemas']['FragmentSelector'];\n\n// Re-export selector types for convenience\nexport type { TextPositionSelector, TextQuoteSelector, SvgSelector, FragmentSelector, Selector };\n\n/**\n * Get the source from an annotation body (null if stub)\n * Search for SpecificResource in body array\n */\nexport function getBodySource(body: Annotation['body']): string | null {\n if (Array.isArray(body)) {\n // Search for SpecificResource with source\n for (const item of body) {\n if (\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n 'source' in item\n ) {\n const itemType = (item as { type: unknown }).type;\n const itemSource = (item as { source: unknown }).source;\n\n if (itemType === 'SpecificResource' && typeof itemSource === 'string') {\n return itemSource;\n }\n }\n }\n return null; // No SpecificResource found = stub\n }\n\n // Single body object (SpecificResource)\n if (\n typeof body === 'object' &&\n body !== null &&\n 'type' in body &&\n 'source' in body\n ) {\n const bodyType = (body as { type: unknown }).type;\n const bodySource = (body as { source: unknown }).source;\n\n if (bodyType === 'SpecificResource' && typeof bodySource === 'string') {\n return bodySource;\n }\n }\n\n return null;\n}\n\n/**\n * Get the type from an annotation body (returns first body type in array)\n */\nexport function getBodyType(body: Annotation['body']): 'TextualBody' | 'SpecificResource' | null {\n if (Array.isArray(body)) {\n if (body.length === 0) {\n return null;\n }\n // Return type of first body item\n if (typeof body[0] === 'object' && body[0] !== null && 'type' in body[0]) {\n const firstType = (body[0] as { type: unknown }).type;\n if (firstType === 'TextualBody' || firstType === 'SpecificResource') {\n return firstType;\n }\n }\n return null;\n }\n\n // Single body object\n if (typeof body === 'object' && body !== null && 'type' in body) {\n const bodyType = (body as { type: unknown }).type;\n if (bodyType === 'TextualBody' || bodyType === 'SpecificResource') {\n return bodyType;\n }\n }\n\n return null;\n}\n\n/**\n * Check if body is resolved (has a source)\n * Check for SpecificResource in body array\n */\nexport function isBodyResolved(body: Annotation['body']): boolean {\n return getBodySource(body) !== null;\n}\n\n/**\n * Get the source IRI from target (handles both string and object forms)\n */\nexport function getTargetSource(target: Annotation['target']): string {\n if (typeof target === 'string') {\n return target;\n }\n return target.source;\n}\n\n/**\n * Get the selector from target (undefined if string or no selector)\n */\nexport function getTargetSelector(target: Annotation['target']) {\n if (typeof target === 'string') {\n return undefined;\n }\n return target.selector;\n}\n\n/**\n * Check if target has a selector\n */\nexport function hasTargetSelector(target: Annotation['target']): boolean {\n return typeof target !== 'string' && target.selector !== undefined;\n}\n\n/**\n * Type guard to check if an annotation is a highlight\n */\nexport function isHighlight(annotation: Annotation): annotation is HighlightAnnotation {\n return annotation.motivation === 'highlighting';\n}\n\n/**\n * Type guard to check if an annotation is a reference (linking)\n */\nexport function isReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return annotation.motivation === 'linking';\n}\n\n/**\n * Type guard to check if an annotation is an assessment\n */\nexport function isAssessment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'assessing';\n}\n\n/**\n * Type guard to check if an annotation is a comment\n */\nexport function isComment(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'commenting';\n}\n\n/**\n * Type guard to check if an annotation is a tag\n */\nexport function isTag(annotation: Annotation): annotation is Annotation {\n return annotation.motivation === 'tagging';\n}\n\n/**\n * Extract comment text from a comment annotation's body\n * @param annotation - The annotation to extract comment text from\n * @returns The comment text, or undefined if not a comment or no text found\n */\nexport function getCommentText(annotation: Annotation): string | undefined {\n if (!isComment(annotation)) return undefined;\n const body = Array.isArray(annotation.body) ? annotation.body[0] : annotation.body;\n if (body && 'value' in body) {\n return body.value;\n }\n return undefined;\n}\n\n/**\n * Type guard to check if a reference annotation is a stub (unresolved)\n * Stub if no SpecificResource in body array\n */\nexport function isStubReference(annotation: Annotation): boolean {\n return isReference(annotation) && !isBodyResolved(annotation.body);\n}\n\n/**\n * Type guard to check if a reference annotation is resolved\n * Resolved if SpecificResource exists in body array\n */\nexport function isResolvedReference(annotation: Annotation): annotation is ReferenceAnnotation {\n return isReference(annotation) && isBodyResolved(annotation.body);\n}\n\n// =============================================================================\n// SELECTOR UTILITIES\n// =============================================================================\n\n/**\n * Get the exact text from a selector (single or array)\n *\n * When selector is an array, tries to find a TextQuoteSelector (which has exact text).\n * TextPositionSelector does not have exact text, only character offsets.\n * Handles undefined selector (when target is a string IRI with no selector)\n */\nexport function getExactText(selector: Selector | Selector[] | undefined): string {\n if (!selector) {\n return ''; // No selector means entire resource\n }\n const selectors = Array.isArray(selector) ? selector : [selector];\n\n // Try to find TextQuoteSelector (has exact text)\n const quoteSelector = selectors.find(s => s.type === 'TextQuoteSelector') as TextQuoteSelector | undefined;\n if (quoteSelector) {\n return quoteSelector.exact;\n }\n\n // No TextQuoteSelector found\n return '';\n}\n\n/**\n * Get the exact text from an annotation's target selector\n * Uses getTargetSelector helper to safely get selector\n */\nexport function getAnnotationExactText(annotation: Annotation): string {\n const selector = getTargetSelector(annotation.target);\n return getExactText(selector as Selector | Selector[] | undefined);\n}\n\n/**\n * Get the primary selector from a selector (single or array)\n *\n * When selector is an array, returns the first selector.\n * When selector is a single object, returns it as-is.\n */\nexport function getPrimarySelector(selector: Selector | Selector[]): Selector {\n if (Array.isArray(selector)) {\n if (selector.length === 0) {\n throw new Error('Empty selector array');\n }\n const first = selector[0];\n if (!first) {\n throw new Error('Invalid selector array');\n }\n return first;\n }\n return selector;\n}\n\n/**\n * Get TextQuoteSelector from a selector (single or array)\n *\n * Returns the first TextQuoteSelector found, or null if none exists.\n */\nexport function getTextQuoteSelector(selector: Selector | Selector[]): TextQuoteSelector | null {\n const selectors = Array.isArray(selector) ? selector : [selector];\n const found = selectors.find(s => s.type === 'TextQuoteSelector');\n if (!found) return null;\n return found.type === 'TextQuoteSelector' ? found : null;\n}\n\n/**\n * Extract bounding box from SVG markup\n *\n * Attempts to extract x, y, width, height from the SVG viewBox or root element.\n * Returns null if bounding box cannot be determined.\n */\nexport function extractBoundingBox(svg: string): { x: number; y: number; width: number; height: number } | null {\n // Try to extract viewBox attribute from SVG element\n const viewBoxMatch = svg.match(/<svg[^>]*viewBox=\"([^\"]+)\"/);\n if (viewBoxMatch) {\n const values = viewBoxMatch[1].split(/\\s+/).map(parseFloat);\n if (values.length === 4 && values.every(v => !isNaN(v))) {\n return {\n x: values[0],\n y: values[1],\n width: values[2],\n height: values[3]\n };\n }\n }\n\n // Try to extract width/height attributes from SVG element (assume x=0, y=0)\n const svgTagMatch = svg.match(/<svg[^>]*>/);\n if (svgTagMatch) {\n const svgTag = svgTagMatch[0];\n const widthMatch = svgTag.match(/width=\"([^\"]+)\"/);\n const heightMatch = svgTag.match(/height=\"([^\"]+)\"/);\n\n if (widthMatch && heightMatch) {\n const width = parseFloat(widthMatch[1]);\n const height = parseFloat(heightMatch[1]);\n\n if (!isNaN(width) && !isNaN(height)) {\n return { x: 0, y: 0, width, height };\n }\n }\n }\n\n return null;\n}\n","/**\n * PDF viewrect FragmentSelector codec.\n *\n * `PdfCoordinate` is a bounding rectangle in PDF point space: origin at the\n * bottom-left of the page, Y increasing upward. The Y-flip to canvas pixels\n * lives in the browser (`react-ui`); the server has no canvas.\n *\n * These functions are the viewrect peer of the W3C `FragmentSelector` wrapper in\n * `web-annotation-utils`: they serialize/parse the RFC 3778\n * `page=N&viewrect=left,top,width,height` value. `@semiont/content` (geometry\n * from the text layer), `@semiont/jobs` (serialization at write time), and the\n * browser canvas all import them from here — no package reaches into the UI.\n *\n * RFC 3778 PDF Fragment Identifiers: https://tools.ietf.org/html/rfc3778\n */\n\n/**\n * A bounding rectangle in PDF point coordinates.\n * Origin at the bottom-left of the page; Y increases upward.\n */\nexport interface PdfCoordinate {\n page: number;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Serialize a PdfCoordinate to an RFC 3778 FragmentSelector value.\n * Format: `page=N&viewrect=left,top,width,height` (all in PDF points).\n */\nexport function createFragmentSelector(coord: PdfCoordinate): string {\n return `page=${coord.page}&viewrect=${coord.x},${coord.y},${coord.width},${coord.height}`;\n}\n\n/**\n * Parse an RFC 3778 FragmentSelector value into PDF coordinates.\n * Returns null when the value is not a well-formed page + viewrect fragment.\n */\nexport function parseFragmentSelector(fragment: string): PdfCoordinate | null {\n const pageMatch = fragment.match(/page=(\\d+)/);\n if (!pageMatch) return null;\n\n // Each coordinate: optional sign, integer part, optional fraction — tight enough\n // to round-trip negatives and reject malformed numbers (e.g. \"1.2.3\").\n const viewrectMatch = fragment.match(\n /viewrect=(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?)/\n );\n if (!viewrectMatch) return null;\n\n return {\n page: parseInt(pageMatch[1], 10),\n x: parseFloat(viewrectMatch[1]),\n y: parseFloat(viewrectMatch[2]),\n width: parseFloat(viewrectMatch[3]),\n height: parseFloat(viewrectMatch[4]),\n };\n}\n\n/** Extract the 1-indexed page number from a FragmentSelector value. */\nexport function getPageFromFragment(fragment: string): number | null {\n const match = fragment.match(/page=(\\d+)/);\n return match ? parseInt(match[1], 10) : null;\n}\n","/**\n * Text ↔ geometry anchoring for PDFs.\n *\n * Two directions over the same pairing of text and the runs that index it:\n * `locate` turns a character span into rectangles (an annotation the model\n * produced by quoting text), `textUnder` turns a rectangle into characters (an\n * annotation a person produced by dragging a box). They are inverses and live\n * together deliberately.\n *\n * This is pure arithmetic over plain data, so it sits here beside\n * `PdfCoordinate` and the viewrect codec rather than in `@semiont/content`:\n * the browser canvas needs `textUnder` at drag time and cannot import\n * `@semiont/content`, which carries pdf.js, Tesseract and `node:fs`.\n * *Producing* an `AnchoredText` — from a text layer or from OCR — stays there.\n *\n * Coordinates are PDF points with the origin at the bottom-left of the page,\n * Y increasing upward. The Y-flip to canvas pixels lives in the browser.\n */\n\nimport type { PdfCoordinate } from './pdf-coordinates';\nimport type { components } from './types';\n\n/**\n * A single text item (one text run, roughly a word) from a PDF.\n * Character offsets refer to positions in the paired `AnchoredText.text`.\n */\nexport interface PdfTextItem {\n start: number; // Char offset in `AnchoredText.text` (inclusive)\n end: number; // Char offset in `AnchoredText.text` (exclusive)\n page: number; // 1-indexed page number\n x: number; // X position in PDF points (origin: bottom-left of page)\n y: number; // Y position in PDF points (origin: bottom-left of page)\n width: number;\n height: number;\n}\n\n/**\n * Text paired with the geometry that indexes it — the minimum needed to turn a\n * character range into a Selection, or a rectangle into a quote.\n *\n * This is the contract `locate`, `textUnder` and the annotation builders\n * actually require; they do not need pages, form fields, or anything else a\n * full `PdfTextLayer` carries. Naming it separately lets OCR'd content\n * (recovered from pixels, so not a \"text layer\" in the PDF sense) satisfy the\n * same anchoring path.\n */\nexport interface AnchoredText {\n text: string;\n items: PdfTextItem[];\n}\n\n/**\n * The full outcome of text extraction for one representation — the record\n * the anchored-text store holds and the wire serves (PERSIST-ANCHORS\n * decision D1): an `AnchoredText` plus its provenance (`method`, `pdfClass`,\n * `ocrConfidence`, `unreadPages`), or a named decline. `AnchoredText` stays\n * the anchoring vocabulary; this is the stored/served record. Aliased from\n * the generated spec type so the wire shape has exactly one authority.\n */\nexport type ExtractionOutcome = components['schemas']['ExtractionOutcome'];\n\n/**\n * One text run as pdf.js reports it, narrowed to the fields anchoring reads.\n * Structural on purpose: core takes no dependency on pdfjs-dist, so each\n * producer filters marked-content items at its own boundary and passes the\n * text runs through.\n */\nexport interface PdfTextRun {\n str: string;\n /** pdf.js text matrix `[a, b, c, d, x, y]`; only x/y are read. */\n transform: number[];\n width: number;\n height: number;\n hasEOL?: boolean;\n}\n\n/**\n * pdf.js interleaves marked-content items with text runs in `getTextContent()`;\n * only the latter carry `str`. Both producers filter with this before calling\n * `anchorRuns`, so the boundary rule is stated once.\n */\nexport function isTextRun<T>(item: T): item is T & PdfTextRun {\n return typeof item === 'object' && item !== null && 'str' in item;\n}\n\n/**\n * Turns one page's pdf.js text runs into `AnchoredText`.\n *\n * This is the offset and separator convention — what `text` says, and where\n * each item points into it. Both producers share it: the server extractor\n * reading a whole document, and the browser canvas reading the page under a\n * drag. Divergence would mean the same rectangle quoting differently depending\n * on which side captured it.\n *\n * Offsets are page-local. A caller assembling a multi-page document shifts them\n * by the length of the text already accumulated.\n */\nexport function anchorRuns(runs: PdfTextRun[], page: number): AnchoredText {\n const items: PdfTextItem[] = [];\n let text = '';\n\n for (const run of runs) {\n if (run.str.trim()) {\n const start = text.length;\n text += run.str;\n const end = text.length; // range covers only this run's own chars\n\n const [, , , , x, y] = run.transform;\n items.push({ start, end, page, x, y, width: run.width, height: run.height });\n\n // Separator AFTER recording the run, so its [start, end) never\n // includes it. pdf.js flags the last run on a line with hasEOL —\n // newline there, space between words otherwise, so reading-order\n // lines don't glue (e.g. \"textsecond\").\n text += run.hasEOL ? '\\n' : ' ';\n } else if (run.hasEOL) {\n // Standalone end-of-line marker (empty/whitespace str): keep the\n // line break without letting whitespace-only runs add stray spaces.\n text += '\\n';\n }\n }\n\n return { text, items };\n}\n\n/**\n * Items whose baseline Y is within this many PDF points are treated as being on\n * the same line. Tuned for ~12pt body text; revisit for documents with large or\n * variable font sizes (Phase 4 / #738).\n */\nconst SAME_LINE_THRESHOLD_PT = 2;\n\n/**\n * Locates bounding rectangles for a span of text in an AnchoredText\n * (single-line or multi-line).\n *\n * Finds all overlapping items [start, end), groups them by page and line, and\n * records one bounding rectangle per line as a PdfCoordinate.\n *\n * Returns both the per-line `rects` and the `overlap` items they were computed\n * from — so a caller that also needs the covered text (e.g. buildPdfAnnotation's\n * geometry↔text containment invariant) reuses this single `items` scan\n * instead of re-filtering. Both arrays are empty if no item overlaps the span.\n */\nexport function locate(\n anchored: AnchoredText,\n start: number,\n end: number\n): { rects: PdfCoordinate[]; overlap: PdfTextItem[] } {\n const overlap: PdfTextItem[] = anchored.items.filter(\n item => item.start < end && item.end > start\n );\n if (overlap.length === 0) return { rects: [], overlap };\n\n const pages: Map<number, PdfTextItem[]> = groupItemsByPage(overlap);\n const rects: PdfCoordinate[] = [];\n\n // for each page, group items into lines and compute one rectangle per line\n for (const [page, pageItems] of pages) {\n const lines = groupItemsByLine(pageItems, SAME_LINE_THRESHOLD_PT);\n // Compute one bounding rectangle per line and add it to rects.\n // Boundary items that extend past [start, end) are clipped by character\n // fraction (PDF-GENERATION P4): renderers like Typst emit ONE item per\n // line, so without clipping a mid-line phrase would bound the whole\n // line. Proportional interpolation is the measured fallback — exact\n // glyph metrics need the operator-list route (open question 2) and can\n // replace this arithmetic without changing the shape.\n for (const lineItems of lines) {\n const edges = lineItems.map(i => {\n const chars = i.end - i.start;\n const left = i.start < start && chars > 0\n ? i.x + i.width * ((start - i.start) / chars)\n : i.x;\n const right = i.end > end && chars > 0\n ? i.x + i.width * ((end - i.start) / chars)\n : i.x + i.width;\n return { left, right };\n });\n const x = Math.min(...edges.map(e => e.left));\n const right = Math.max(...edges.map(e => e.right));\n const y = Math.min(...lineItems.map(i => i.y));\n const top = Math.max(...lineItems.map(i => i.y + i.height));\n rects.push({page, x, y, width: right - x, height: top - y});\n }\n }\n return { rects, overlap };\n}\n\n/**\n * The inverse of `locate`: given a rectangle, returns the text under it.\n *\n * A hand-drawn PDF rectangle otherwise carries no quoted text at all, so every\n * panel that quotes an annotation shows it blank\n * (.plans/PDF-MANUAL-ANNOTATION-TEXT.md).\n *\n * `rect` is in the same PDF-point, bottom-left-origin space as `PdfTextItem`,\n * so a canvas drag rectangle passes straight in. A run counts as covered when\n * the rectangle overlaps `RUN_COVERAGE_THRESHOLD` of its area — see there for\n * why any-intersection is not survivable for a hand-drawn box.\n *\n * Covered runs are emitted in reading order (`text` offset order), which\n * inherits the extractor's known column-major ordering on multi-column pages\n * rather than answering it a second, different way.\n *\n * Returns `''` when nothing is covered — over an image, over whitespace, or\n * over a scanned page with no text layer. Callers must then emit no\n * `TextQuoteSelector` at all: an empty quote would assert the box was drawn\n * around nothing.\n */\nexport function textUnder(anchored: AnchoredText, rect: PdfCoordinate): string {\n const covered = anchored.items\n .filter(item => item.page === rect.page && covers(item, rect))\n .sort((a, b) => a.start - b.start);\n if (covered.length === 0) return '';\n\n // Join with the document's own separator when the runs are adjacent in\n // `text` — pdf.js splits words at kerning and font changes, so a blanket\n // join(' ') would emit \"aga in\" for a single word. When runs are NOT\n // adjacent the rectangle missed the text between them, so substitute a\n // space rather than splicing in words the box does not cover. (Slicing\n // first-offset..last-offset the way buildPdfAnnotation does is safe there\n // — it only feeds a containment check — but here the result is the stored\n // quote, and on a two-column page it would swallow half of each column.)\n let quoted = slice(anchored, covered[0]);\n for (let i = 1; i < covered.length; i++) {\n const gap = anchored.text.slice(covered[i - 1].end, covered[i].start);\n quoted += (gap.trim() === '' ? gap : ' ') + slice(anchored, covered[i]);\n }\n return quoted.trim();\n}\n\nconst slice = (anchored: AnchoredText, item: PdfTextItem): string =>\n anchored.text.slice(item.start, item.end);\n\n/**\n * Fraction of a run's own area a rectangle must overlap for the run to count\n * as covered.\n *\n * Any intersection — the obvious rule, and `locate`'s rule for offsets — is not\n * survivable here, because a hand-drawn box is not a tight box. What decides\n * the threshold is the *headroom* between lines: word boxes run taller than\n * their glyphs, so the gap between one line's box and the next is far smaller\n * than the visible leading. Exact-quote rate measured over every text page of\n * two real scanned books, by how far the box misses:\n *\n * any 0.3 0.4 0.5 0.6\n * -2pt 98/99 98/83 98/49 60/16 2/ 0\n * -1pt 98/99 98/100 98/97 98/94 98/84\n * +2pt 45/ 2 98/97 98/99 98/99 98/100\n * +4pt 11/ 2 98/16 98/58 98/96 98/97\n * +6pt 9/ 0 51/ 8 64/11 98/16 98/38\n * (headroom ~2.0pt / ~0.9pt — the second book is set much tighter,\n * and on some of its pages adjacent word boxes overlap outright)\n *\n * A third book, 100 pages, varies run granularity instead — ~42 chars per run\n * against 25 and 14, i.e. whole lines as single runs — and 0.5 holds 100% from\n * -1pt to +6pt there. Across all three: >=94% from -1pt to +4pt every time.\n *\n * This also carries page skew, which is why it matters beyond hand-drawn boxes.\n * Tilting real runs and taking axis-aligned boxes after rotation, exact-quote\n * rate: 0.5 holds 100% to 0.25deg and 99% at 0.5deg, where `any` is already at\n * 54% and 34% — a tenth of a degree, invisible to the eye, is enough to wreck\n * it. Beyond ~1deg the limit is not this constant but `SAME_LINE_THRESHOLD_PT`,\n * which a drifting baseline exceeds, splitting one line into several rects.\n *\n * Any-intersection is exact only while the box is tight: 2pt of overshoot —\n * less than the height of a comma, and unavoidable with a mouse — and quotes\n * start picking up fragments of the lines above and below.\n *\n * 0.5 is the widest band holding on BOTH books, about 1pt under to 4pt over.\n * Lower thresholds look better on loosely-set pages and fail on tight ones\n * (0.3 drops to 16% at +4pt on the tighter book), which is exactly the way to\n * overfit this constant to one document. A hand drag overshoots far more often\n * than it undershoots, so the asymmetry is spent on the overshoot side.\n *\n * Consequence to know about: a run the box merely clips — a sliver of the\n * first or last word — falls below the threshold and is dropped. That is the\n * intended trade. Raising this admits neighbouring lines; lowering it drops\n * words from a box drawn slightly small.\n */\nexport const RUN_COVERAGE_THRESHOLD = 0.5;\n\nfunction covers(item: PdfTextItem, rect: PdfCoordinate): boolean {\n const overlapX = Math.min(item.x + item.width, rect.x + rect.width) - Math.max(item.x, rect.x);\n const overlapY = Math.min(item.y + item.height, rect.y + rect.height) - Math.max(item.y, rect.y);\n if (overlapX <= 0 || overlapY <= 0) return false;\n return overlapX * overlapY >= RUN_COVERAGE_THRESHOLD * item.width * item.height;\n}\n\nfunction groupItemsByPage(items: PdfTextItem[]): Map<number, PdfTextItem[]> {\n const map = new Map<number, PdfTextItem[]>();\n for (const item of items) {\n const existing = map.get(item.page);\n if (existing) {\n existing.push(item);\n } else {\n map.set(item.page, [item]);\n }\n }\n return map;\n}\n\n\n/**\n * Sorts text items into lines when their y coordinates are\n * within `sameLineThreshold` points of each other.\n * Sorted top-to-bottom (descending y in PDF space), then left-to-right.\n *\n * Returns 2D array:\n * Outer array = list of lines\n * Inner array = list of items on that line\n*/\nfunction groupItemsByLine(items: PdfTextItem[], sameLineThreshold: number): PdfTextItem[][] {\n // Sort top-to-bottom by y; if y is equal, sort left-to-right by x\n const sorted = [...items].sort((a, b) => b.y - a.y || a.x - b.x);\n const lines: PdfTextItem[][] = [];\n let currentLine: PdfTextItem[] = [];\n\n for (const item of sorted) {\n if (currentLine.length === 0 || Math.abs(item.y - currentLine[0].y) <= sameLineThreshold) {\n currentLine.push(item);\n } else {\n lines.push(currentLine);\n currentLine = [item];\n }\n }\n if (currentLine.length > 0) lines.push(currentLine);\n return lines;\n}\n","/**\n * Two-stage citation search over an extracted PDF text layer\n * (PDF-GENERATION P4).\n *\n * A citation's `exact` claim text comes from the authored source; the rendered\n * text layer diverges from it in exactly two measured ways (the P0 spike):\n * line breaks (`anchorRuns` joins runs with \" \\n\") and hyphenation (soft\n * hyphens are DROPPED — a hyphenated word yields its two halves with no hyphen\n * character anywhere).\n *\n * Two stages, in this order, never collapsed to one matcher:\n *\n * 1. STRICT — search a whitespace-normalized copy, offsets mapped back.\n * Bridges plain line breaks (\" \\n\" collapses to \" \").\n * 2. BREAK-AWARE — only on a strict miss. The line break becomes a distinct\n * marker character that may be absorbed in any inter-character gap, with\n * an optional space on either side (anchorRuns emits a space *then* the\n * newline). Ordinary spaces are NEVER wildcards, so \"abc\" cannot match\n * \"a b c\" — only a real break is absorbable.\n *\n * The ordering is the safety property: the permissive matcher runs only where\n * the strict one already failed, so it can never turn a working citation into\n * a wrong one — only a failure into an unlikely mismatch.\n */\nimport type { AnchoredText } from './pdf-anchoring';\n\n/** Distinct break marker — deliberately not a space (spaces are never wildcards). */\nconst BREAK_MARKER = '\u0001';\n\n/** Optional-break gap: the marker, with an optional space on either side. */\nconst BREAK_GAP = `(?: ?${BREAK_MARKER} ?)?`;\n\nconst escapeRegExp = (ch: string): string => ch.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nexport function findClaimSpan(\n anchored: AnchoredText,\n exact: string,\n): { start: number; end: number } | null {\n const needle = exact.replace(/\\s+/g, ' ').trim();\n if (needle.length === 0) return null;\n\n // ── Stage 1: strict, over a whitespace-normalized copy with an offset map ──\n let norm = '';\n const map: number[] = [];\n let pendingWsAt = -1;\n for (let i = 0; i < anchored.text.length; i++) {\n const ch = anchored.text[i]!;\n if (/\\s/.test(ch)) {\n if (norm.length > 0 && pendingWsAt < 0) pendingWsAt = i;\n continue;\n }\n if (pendingWsAt >= 0) {\n norm += ' ';\n map.push(pendingWsAt);\n pendingWsAt = -1;\n }\n norm += ch;\n map.push(i);\n }\n const idx = norm.indexOf(needle);\n if (idx >= 0) {\n return { start: map[idx]!, end: map[idx + needle.length - 1]! + 1 };\n }\n\n // ── Stage 2: break-aware, only on a miss ──\n const marker = anchored.text.replace(/\\n/g, BREAK_MARKER);\n const pattern = [...needle].map(escapeRegExp).join(BREAK_GAP);\n const match = new RegExp(pattern).exec(marker);\n if (match) {\n return { start: match.index, end: match.index + match[0].length };\n }\n\n return null;\n}\n","/**\n * Helper functions for working with W3C ResourceDescriptor\n */\n\nimport type { components } from './types';\nimport type { ResourceDescriptor } from './graph';\n\ntype Representation = components['schemas']['Representation'];\n\n/**\n * Get the resource ID from @id property\n *\n * @id is always a bare ID (UUID), never a full URI.\n */\nexport function getResourceId(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource) return undefined;\n return resource['@id'] || undefined;\n}\n\n/**\n * Get the primary representation (first or only representation)\n */\nexport function getPrimaryRepresentation(resource: ResourceDescriptor | undefined): Representation | undefined {\n if (!resource?.representations) return undefined;\n const reps = Array.isArray(resource.representations)\n ? resource.representations\n : [resource.representations];\n return reps[0];\n}\n\n/**\n * Get the media type from the primary representation\n */\nexport function getPrimaryMediaType(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.mediaType;\n}\n\n/**\n * Get the checksum from the primary representation\n */\nexport function getChecksum(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.checksum;\n}\n\n/**\n * Get the language from the primary representation\n */\nexport function getLanguage(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.language;\n}\n\n/**\n * Get storage URI from primary representation\n *\n * @param resource - ResourceDescriptor\n * @returns Storage URI or undefined\n */\nexport function getStorageUri(resource: ResourceDescriptor | undefined): string | undefined {\n return getPrimaryRepresentation(resource)?.storageUri;\n}\n\n/**\n * Get creator agent from wasAttributedTo\n * Handles both single agent and array of agents\n *\n * @param resource - ResourceDescriptor\n * @returns First agent or undefined\n */\nexport function getCreator(resource: ResourceDescriptor | undefined): components['schemas']['Agent'] | undefined {\n if (!resource?.wasAttributedTo) return undefined;\n\n return Array.isArray(resource.wasAttributedTo)\n ? resource.wasAttributedTo[0]\n : resource.wasAttributedTo;\n}\n\n/**\n * Get derived-from URI\n * Handles both single URI and array of URIs\n *\n * @param resource - ResourceDescriptor\n * @returns First derivation URI or undefined\n */\nexport function getDerivedFrom(resource: ResourceDescriptor | undefined): string | undefined {\n if (!resource?.wasDerivedFrom) return undefined;\n\n return Array.isArray(resource.wasDerivedFrom)\n ? resource.wasDerivedFrom[0]\n : resource.wasDerivedFrom;\n}\n\n/**\n * Check if resource is archived (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if archived, false otherwise\n */\nexport function isArchived(resource: ResourceDescriptor | undefined): boolean {\n return resource?.archived === true;\n}\n\n/**\n * Get entity types from resource (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns Array of entity types, empty if not set\n */\nexport function getResourceEntityTypes(resource: ResourceDescriptor | undefined): string[] {\n return resource?.entityTypes || [];\n}\n\n/**\n * Check if resource is a draft (application-specific field)\n *\n * @param resource - ResourceDescriptor\n * @returns True if draft, false otherwise\n */\nexport function isDraft(resource: ResourceDescriptor | undefined): boolean {\n return resource?.isDraft === true;\n}\n\n/**\n * Map charset names to Node.js Buffer encoding names\n * Node.js Buffer.toString() supports: 'utf8', 'utf16le', 'latin1', 'base64', 'hex', 'ascii', 'binary', 'ucs2'\n *\n * @param charset - Charset name (e.g., \"UTF-8\", \"ISO-8859-1\", \"Windows-1252\")\n * @returns Node.js BufferEncoding\n */\nexport function getNodeEncoding(charset: string): BufferEncoding {\n const normalized = charset.toLowerCase().replace(/[-_]/g, '');\n\n // Map common charset names to Node.js encodings\n const charsetMap: Record<string, BufferEncoding> = {\n 'utf8': 'utf8',\n 'iso88591': 'latin1',\n 'latin1': 'latin1',\n 'ascii': 'ascii',\n 'usascii': 'ascii',\n 'utf16le': 'utf16le',\n 'ucs2': 'ucs2',\n 'binary': 'binary',\n 'windows1252': 'latin1', // Windows-1252 is a superset of Latin-1\n 'cp1252': 'latin1',\n };\n\n return charsetMap[normalized] || 'utf8';\n}\n\n/**\n * Decode a representation buffer to string using the correct charset\n * Extracts charset from media type and uses appropriate encoding\n *\n * @param buffer - The raw representation data\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=iso-8859-1\")\n * @returns Decoded string\n *\n * @example\n * ```typescript\n * const content = decodeRepresentation(buffer, \"text/plain; charset=utf-8\");\n * const legacy = decodeRepresentation(buffer, \"text/plain; charset=windows-1252\");\n * ```\n */\nexport function decodeRepresentation(buffer: Buffer, mediaType: string): string {\n // Extract charset from mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n const charset = (charsetMatch?.[1] || 'utf-8').toLowerCase();\n\n // Map to Node.js encoding\n const encoding = getNodeEncoding(charset);\n\n return buffer.toString(encoding);\n}\n","/**\n * Common error classes — the unified Semiont error hierarchy.\n *\n * `SemiontError` is the base every other Semiont error class extends:\n * `APIError` (http-transport), `BusRequestError` and `SemiontSessionError` (sdk),\n * `ValidationError`, `ScriptError`, `NotFoundError`, `UnauthorizedError`,\n * `ConflictError` (here), and `AWSError` (cli). Subclasses tighten the\n * `code` field to a literal-union for discriminated handling.\n */\n\n/**\n * Transport-neutral error vocabulary. Every transport that surfaces\n * errors over `ITransport.errors$` maps its native failure modes to one\n * of these codes — HTTP `APIError` maps from status code, in-process\n * transports map from local failure shape, gRPC would map from status\n * code, etc. Routing layers (e.g. `SemiontBrowser`'s session-expired /\n * permission-denied modal routing) match on this vocabulary so they\n * stay transport-agnostic.\n *\n * - `unauthorized` — auth required / token missing or expired (HTTP 401)\n * - `forbidden` — auth ok but lacks permission (HTTP 403)\n * - `not-found` — resource missing (HTTP 404)\n * - `conflict` — concurrent modification, duplicate, etc. (HTTP 409)\n * - `bad-request` — request malformed (HTTP 400)\n * - `unavailable` — backend unreachable, network error, 5xx\n * - `error` — unclassified fallback\n */\nexport type TransportErrorCode =\n | 'unauthorized'\n | 'forbidden'\n | 'not-found'\n | 'conflict'\n | 'bad-request'\n | 'unavailable'\n | 'error';\n\nexport class SemiontError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'SemiontError';\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class ValidationError extends SemiontError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'VALIDATION_ERROR', details);\n this.name = 'ValidationError';\n }\n}\n\nexport class ScriptError extends SemiontError {\n constructor(message: string, code: string = 'SCRIPT_ERROR', details?: Record<string, unknown>) {\n super(message, code, details);\n this.name = 'ScriptError';\n }\n}\n\nexport class NotFoundError extends SemiontError {\n constructor(resource: string, id?: string) {\n const message = id ? `${resource} with id '${id}' not found` : `${resource} not found`;\n super(message, 'NOT_FOUND', { resource, id });\n this.name = 'NotFoundError';\n }\n}\n\nexport class UnauthorizedError extends SemiontError {\n constructor(message: string = 'Unauthorized', details?: Record<string, unknown>) {\n super(message, 'UNAUTHORIZED', details);\n this.name = 'UnauthorizedError';\n }\n}\n\nexport class ConflictError extends SemiontError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'CONFLICT', details);\n this.name = 'ConflictError';\n }\n}\n","import { Observable, firstValueFrom, merge, throwError, TimeoutError } from 'rxjs';\nimport { catchError, defaultIfEmpty, filter, map, take, timeout } from 'rxjs/operators';\nimport { SemiontError } from './errors';\nimport type { EventMap, EventName } from './bus-protocol';\nimport type { ConnectionState } from './transport';\nimport { BUS_OPERATIONS, type BusOperationKey } from './bus-operations';\nimport { uuidV4 } from './id-generation';\n\n/**\n * The value a registered operation resolves to: the `response` field of its\n * result channel's payload, or `void` for a result channel that carries no\n * `response` (a confirmed-write ack with no data). Inferred from the registry,\n * so callers never annotate `busRequest`'s return type. Relies on the reply-shape\n * standard — see .plans/REPLY-SHAPE-STANDARD.md.\n */\nexport type BusReply<Op extends BusOperationKey> =\n EventMap[(typeof BUS_OPERATIONS)[Op]['result'] & EventName] extends { response: infer R }\n ? R\n : void;\n\nexport type BusRequestErrorCode =\n | 'bus.timeout'\n | 'bus.rejected'\n | 'bus.closed'\n | 'bus.bad-payload'\n | 'bus.unauthorized'\n | 'bus.forbidden'\n | 'bus.not-found';\n\nexport class BusRequestError extends SemiontError {\n declare code: BusRequestErrorCode;\n\n constructor(message: string, code: BusRequestErrorCode, details?: Record<string, unknown>) {\n super(message, code, details);\n this.name = 'BusRequestError';\n }\n}\n\n/**\n * Subset of ITransport that `busRequest` needs: a way to send a command and\n * a way to observe channels. Generic enough that an in-process transport\n * can satisfy it without round-tripping through HTTP.\n */\nexport interface BusRequestPrimitive {\n /**\n * Matches `ITransport.emit`'s return: the subscriber count (`-1` =\n * unknown). `busRequest` itself ignores it — the reply channel is its\n * ack — but the primitive must stay assignable from every ITransport.\n */\n emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): Promise<number>;\n stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;\n /**\n * Connection state of the stream that carries replies. Required, not\n * optional (.plans/BUS-ATTACH-GATE.md D2): `busRequest` gates its emit on\n * this — no correlated emit before the reply path exists. Implementers back\n * it with a `BehaviorSubject`, so the current state arrives synchronously\n * on subscribe; a transport that cannot lose replies (in-process) reports\n * `'open'` until disposal.\n */\n state$: Observable<ConnectionState>;\n /**\n * Correlated-reply retention, client side (.plans/BUS-RESUMPTION.md\n * Phase 2 / SDK-DEBT S1). `busRequest` registers its correlationId here\n * BEFORE emitting and calls the returned disposer on every settle path;\n * a wire transport includes the currently-tracked ids as\n * `pendingReplies` in each subscribe body, so a reply published while\n * the connection was down is replayed from the server's retention\n * buffer on reconnect. OPTIONAL: an in-process transport that cannot\n * lose replies omits the surface and `busRequest` behaves as before.\n */\n trackReply?(correlationId: string): () => void;\n}\n\n/**\n * Request/reply over the bus, keyed by the operation's request channel.\n *\n * The `operation` is a `BusOperationKey` (a request channel declared in\n * `BUS_OPERATIONS`); the matching `result`/`failure` reply channels are looked\n * up from the registry, so a caller cannot pass a mismatched or unbridged reply\n * pair — the recurring unbridged-reply bug class is unrepresentable. Every\n * registry reply derives into `BRIDGED_CHANNELS` (see bridged-channels.ts), so\n * the transport always subscribes to it (cf.\n * .plans/bugs/gather-resource-complete-not-bridged.md, where the `gather:resource-*`\n * pair shipped unbridged with no compile/runtime signal).\n *\n * The return type is INFERRED from the registry (`BusReply<Op>` = the result\n * channel's `response` type, or `void`) — callers never annotate it. Every reply\n * is `{ correlationId, response: T }` (data) or `{ correlationId }` (void); see\n * .plans/REPLY-SHAPE-STANDARD.md. `busRequest` reads `e.response`.\n */\nexport async function busRequest<Op extends BusOperationKey>(\n bus: BusRequestPrimitive,\n operation: Op,\n payload: Record<string, unknown>,\n timeoutMs = 30_000,\n): Promise<BusReply<Op>> {\n const correlationId = uuidV4();\n const fullPayload = { ...payload, correlationId };\n const { result: resultChannel, failure: failureChannel } = BUS_OPERATIONS[operation];\n\n const result$ = merge(\n (bus.stream(resultChannel as keyof EventMap) as Observable<Record<string, unknown>>).pipe(\n filter((e) => e.correlationId === correlationId),\n map((e) => ({ ok: true as const, response: e.response as BusReply<Op> })),\n ),\n (bus.stream(failureChannel as keyof EventMap) as Observable<Record<string, unknown>>).pipe(\n filter((e) => e.correlationId === correlationId),\n map((e) => ({\n ok: false as const,\n error: new BusRequestError((e.message as string) ?? 'Bus request rejected', 'bus.rejected', {\n channel: failureChannel,\n correlationId,\n payload: e,\n }),\n })),\n ),\n ).pipe(\n take(1),\n timeout(timeoutMs),\n catchError((err) => {\n if (err instanceof TimeoutError) {\n return throwError(\n () =>\n new BusRequestError(\n `Bus request timed out after ${timeoutMs}ms on ${resultChannel}`,\n 'bus.timeout',\n { channel: operation, resultChannel, correlationId, timeoutMs },\n ),\n );\n }\n return throwError(() => err);\n }),\n // If the stream completes with no value — the bus was disposed before a\n // reply (e.g. during `semiont.dispose()` with a request in flight) —\n // resolve to a typed `bus.closed` result instead of letting `firstValueFrom`\n // throw rxjs `EmptyError`. An awaited caller then gets a clean\n // BusRequestError; an in-flight promise nobody is awaiting simply resolves,\n // so it can't surface as an unhandled rejection on dispose.\n // See .plans/bugs/busrequest-emptyerror-on-dispose.md.\n defaultIfEmpty({\n ok: false as const,\n error: new BusRequestError(\n `Bus closed before a reply on ${resultChannel}`,\n 'bus.closed',\n { channel: operation, resultChannel, correlationId },\n ),\n }),\n );\n\n // Subscribe before emitting so we don't miss an instantaneous reply\n // (which can happen with an in-process LocalTransport bus).\n const resultPromise = firstValueFrom(result$);\n\n // ── Attach gate (.plans/BUS-ATTACH-GATE.md) ─────────────────────────────\n // No correlated emit before the reply path exists: the measured failure was\n // an emit accepted (202) and answered while the session's subscribe stream\n // had not attached — the reply was published to nobody. Wait, inside the\n // SAME deadline (the timeout operator above is already ticking — D4), for\n // the transport to report the one deliverable state. D3 (amended\n // 2026-07-29): only `'open'` delivers; `'degraded'` is a dropped stream by\n // definition and waits like `connecting`/`reconnecting`. `'closed'` fails\n // fast — a request against a closed bus should not burn a timeout.\n const closedBeforeEmit = () => {\n // Detach the reply promise before throwing, same discipline as the emit\n // rejection path below: nobody will await it, and it must not surface\n // later as an unhandled rejection.\n resultPromise.catch(() => {});\n return new BusRequestError(`Bus closed before emit on ${operation}`, 'bus.closed', {\n channel: operation,\n correlationId,\n });\n };\n\n // Synchronous fast path: `state$` is BehaviorSubject-backed (see the\n // interface contract), so the current state lands during subscribe. Already\n // `'open'` → fall straight through to the emit with zero added microtasks —\n // the gate can only remove latency, never add it (D4).\n let currentState: ConnectionState | undefined;\n bus.state$.subscribe((s) => {\n currentState = s;\n }).unsubscribe();\n\n if (currentState === 'closed') {\n throw closedBeforeEmit();\n }\n let emitAllowed = currentState === 'open';\n if (!emitAllowed) {\n const gate = firstValueFrom(\n bus.state$.pipe(\n filter((s) => s === 'open' || s === 'closed'),\n take(1),\n // `state$` completed without ever attaching: treat as closed.\n defaultIfEmpty('closed' as ConnectionState),\n ),\n );\n const outcome = await Promise.race([\n gate,\n // Either settlement of the reply machinery means \"stop waiting, never\n // emit\": its timeout rejecting `bus.timeout` at `timeoutMs` (the same\n // moment it would fire today — D4), or its streams completing into the\n // `bus.closed` default above. The shared tail below carries it.\n resultPromise.then(\n () => 'settled' as const,\n () => 'settled' as const,\n ),\n ]);\n if (outcome === 'closed') {\n // The abandoned race arm cannot reject (filter + defaultIfEmpty), so\n // only the reply promise needs detaching — closedBeforeEmit does it.\n throw closedBeforeEmit();\n }\n // 'open' → the one emit below. 'settled' → skip the emit; awaiting the\n // reply at the tail rethrows its outcome. (D5 holds structurally either\n // way: nothing subscribes to state$ past this point, so a flap after\n // emission cannot re-emit.)\n emitAllowed = outcome === 'open';\n }\n\n // An emit rejection (e.g. /bus/emit 4xx) propagates to the caller — but the\n // caller then never awaits `resultPromise`, which is already subscribed and\n // will REJECT with `bus.timeout` at `timeoutMs` (the request never left, so\n // no reply can save it). Detach it before rethrowing so the doomed promise\n // can't surface later as an unhandled rejection. (`defaultIfEmpty` covers\n // only the disposed-bus case, where the stream completes and the promise\n // *resolves* `bus.closed`.) Found by the liveness harness's reject-emit\n // schedules (.plans/LIVENESS-AXIOMS.md, P1).\n //\n // Reply tracking (BUS-RESUMPTION.md Phase 2 / SDK-DEBT S1): register the\n // cid BEFORE the emit — a reconnect body built while the emit is in flight\n // must already carry it in `pendingReplies`, or a reply published in the\n // old-connection-death → new-connection-open gap sits in the server's\n // retention buffer unasked-for. Released on every settle path; the\n // never-emitted paths above (closed fast-fail, 'settled' race arm) never\n // reach this line, so they never track.\n let releaseTracking: (() => void) | undefined;\n if (emitAllowed) {\n releaseTracking = bus.trackReply?.(correlationId);\n try {\n await bus.emit(operation as keyof EventMap, fullPayload as EventMap[keyof EventMap]);\n } catch (emitError) {\n releaseTracking?.();\n releaseTracking = undefined;\n resultPromise.catch(() => {});\n throw emitError;\n }\n }\n\n try {\n const result = await resultPromise;\n if (!result.ok) {\n throw result.error;\n }\n return result.response;\n } finally {\n releaseTracking?.();\n }\n}\n","/**\n * Fuzzy Anchoring for W3C Web Annotation TextQuoteSelector\n *\n * Uses prefix/suffix context to disambiguate when the same text appears multiple times.\n * Implements fuzzy matching as specified in the W3C Web Annotation Data Model.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nexport interface TextPosition {\n start: number;\n end: number;\n}\n\nexport type MatchQuality = 'exact' | 'normalized' | 'case-insensitive' | 'fuzzy';\n\n/**\n * Normalize text for comparison - handles common document editing changes\n *\n * Collapses whitespace, converts curly quotes to straight quotes,\n * and normalizes common punctuation variations.\n */\nexport function normalizeText(text: string): string {\n return text\n .replace(/\\s+/g, ' ') // collapse whitespace\n .replace(/[\\u2018\\u2019]/g, \"'\") // curly single quotes → straight\n .replace(/[\\u201C\\u201D]/g, '\"') // curly double quotes → straight\n .replace(/\\u2014/g, '--') // em-dash → double hyphen\n .replace(/\\u2013/g, '-') // en-dash → hyphen\n .trim();\n}\n\n/**\n * Calculate Levenshtein distance between two strings\n * Used for fuzzy matching when exact text doesn't match\n */\nfunction levenshteinDistance(str1: string, str2: string): number {\n const len1 = str1.length;\n const len2 = str2.length;\n const matrix: number[][] = [];\n\n // Initialize matrix\n for (let i = 0; i <= len1; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= len2; j++) {\n matrix[0]![j] = j;\n }\n\n // Fill matrix\n for (let i = 1; i <= len1; i++) {\n for (let j = 1; j <= len2; j++) {\n const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;\n const deletion = matrix[i - 1]![j]! + 1;\n const insertion = matrix[i]![j - 1]! + 1;\n const substitution = matrix[i - 1]![j - 1]! + cost;\n matrix[i]![j] = Math.min(deletion, insertion, substitution);\n }\n }\n\n return matrix[len1]![len2]!;\n}\n\n/**\n * Pre-computed content strings for batch fuzzy matching.\n * Avoids recomputing normalizeText(content) and content.toLowerCase()\n * for every annotation when processing many annotations against the same content.\n *\n * `normalizedMap[i]` is the original-content index that normalized\n * character `i` came from. It has length `normalizedContent.length + 1`;\n * the final entry is `content.length` so a match that ends at the end of\n * the normalized string maps back to the end of the original. This map is\n * how `findBestTextMatch` recovers the *original* offset of a normalized\n * match — counting char-by-char with `normalizeText(singleChar)` is\n * wrong, because a lone whitespace char trims to `''` (contributing 0)\n * while in a full-string normalize it collapses to a single space\n * (contributing 1). That discrepancy shifted recovered offsets by the\n * number of whitespace runs before the match.\n */\nexport interface ContentCache {\n normalizedContent: string;\n normalizedMap: number[];\n lowerContent: string;\n}\n\n/**\n * Normalize text and, in the same pass, build a map from each normalized\n * character position back to the original-content index it came from.\n * The produced `normalized` string is identical to `normalizeText(input)`\n * — a test pins this equivalence so the two can't drift.\n */\nexport function normalizeTextWithMap(input: string): { normalized: string; map: number[] } {\n let normalized = '';\n const map: number[] = [];\n\n // First pass mirrors normalizeText exactly, char by char, recording the\n // origin index for every emitted normalized character.\n let pendingWhitespaceStart = -1; // origin index of an open whitespace run, or -1\n\n const flushWhitespace = () => {\n if (pendingWhitespaceStart !== -1) {\n // A whitespace run collapses to a single space, mapped to the run's\n // first char — but a *leading* run (nothing emitted yet) is dropped,\n // matching normalizeText's trailing `.trim()`.\n if (normalized.length > 0) {\n normalized += ' ';\n map.push(pendingWhitespaceStart);\n }\n pendingWhitespaceStart = -1;\n }\n };\n\n for (let i = 0; i < input.length; i++) {\n const ch = input[i]!;\n if (/\\s/.test(ch)) {\n if (pendingWhitespaceStart === -1) pendingWhitespaceStart = i;\n continue;\n }\n flushWhitespace();\n if (ch === '‘' || ch === '’') {\n normalized += \"'\"; map.push(i);\n } else if (ch === '“' || ch === '”') {\n normalized += '\"'; map.push(i);\n } else if (ch === '—') {\n normalized += '--'; map.push(i); map.push(i);\n } else if (ch === '–') {\n normalized += '-'; map.push(i);\n } else {\n normalized += ch; map.push(i);\n }\n }\n // A trailing whitespace run is dropped by trim — do not flush it.\n\n // `normalizeText` applies `.trim()` last. Our run logic already drops a\n // trailing whitespace run; a leading run is dropped because flushWhitespace\n // only runs before a non-space char, so a run at the very start is never\n // emitted. Both ends match trim().\n map.push(input.length); // sentinel: one past the last normalized char\n return { normalized, map };\n}\n\n/**\n * Build a ContentCache for a given content string.\n * Call once per content, pass to findBestTextMatch/anchorAnnotation for all annotations.\n */\nexport function buildContentCache(content: string): ContentCache {\n const { normalized, map } = normalizeTextWithMap(content);\n return {\n normalizedContent: normalized,\n normalizedMap: map,\n lowerContent: content.toLowerCase()\n };\n}\n\n/**\n * Find best match for text in content using multi-strategy search\n *\n * Shared core logic used by both anchorAnnotation (render-time) and\n * reconcileSelector (write-time).\n *\n * @param content - Full text content to search within\n * @param searchText - The text to find\n * @param positionHint - Hint for where to search (TextPositionSelector.start)\n * @param cache - Pre-computed normalized/lowered content (from buildContentCache)\n * @returns Match with position and quality, or null if not found\n */\nexport function findBestTextMatch(\n content: string,\n searchText: string,\n positionHint: number | undefined,\n cache: ContentCache\n): { start: number; end: number; matchQuality: MatchQuality } | null {\n const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05)); // 5% tolerance or min 5 chars\n\n // Strategy 1: Exact match (case-sensitive, exact whitespace)\n const exactIndex = content.indexOf(searchText);\n if (exactIndex !== -1) {\n return {\n start: exactIndex,\n end: exactIndex + searchText.length,\n matchQuality: 'exact'\n };\n }\n\n // Strategy 2: Normalized match (handles whitespace/quote variations).\n // Map the normalized match position back to the original via the\n // precomputed index map. The naive char-by-char re-normalize is wrong:\n // a lone whitespace char trims to '' (0-width) but collapses to a single\n // space (1-width) in a full normalize, so it under-counts by the number\n // of whitespace runs before the match, shifting the recovered offset.\n const normalizedSearch = normalizeText(searchText);\n const normalizedIndex = cache.normalizedContent.indexOf(normalizedSearch);\n if (normalizedIndex !== -1) {\n const start = cache.normalizedMap[normalizedIndex] ?? 0;\n const end = cache.normalizedMap[normalizedIndex + normalizedSearch.length] ?? content.length;\n return {\n start,\n end,\n matchQuality: 'normalized'\n };\n }\n\n // Strategy 3: Case-insensitive match\n const lowerSearch = searchText.toLowerCase();\n const caseInsensitiveIndex = cache.lowerContent.indexOf(lowerSearch);\n if (caseInsensitiveIndex !== -1) {\n return {\n start: caseInsensitiveIndex,\n end: caseInsensitiveIndex + searchText.length,\n matchQuality: 'case-insensitive'\n };\n }\n\n // Strategy 4: Fuzzy match using Levenshtein distance with sliding window\n // Search near position hint if provided, otherwise search full content\n const windowSize = searchText.length;\n const searchRadius = Math.min(500, content.length);\n const searchStart = positionHint !== undefined\n ? Math.max(0, positionHint - searchRadius)\n : 0;\n const searchEnd = positionHint !== undefined\n ? Math.min(content.length, positionHint + searchRadius)\n : content.length;\n\n let bestMatch: { start: number; distance: number } | null = null;\n\n // Scan through content with sliding window\n for (let i = searchStart; i <= searchEnd - windowSize; i++) {\n const candidate = content.substring(i, i + windowSize);\n const distance = levenshteinDistance(searchText, candidate);\n\n if (distance <= maxFuzzyDistance) {\n if (!bestMatch || distance < bestMatch.distance) {\n bestMatch = { start: i, distance };\n }\n }\n }\n\n if (bestMatch) {\n return {\n start: bestMatch.start,\n end: bestMatch.start + windowSize,\n matchQuality: 'fuzzy'\n };\n }\n\n return null;\n}\n\n/**\n * Verify that a position correctly points to the exact text\n * Useful for debugging and validation\n */\nexport function verifyPosition(\n content: string,\n position: TextPosition,\n expectedExact: string\n): boolean {\n const actualText = content.substring(position.start, position.end);\n return actualText === expectedExact;\n}\n","/**\n * Anchor a W3C Web Annotation to its rendered text.\n *\n * Render-time cleverness is deliberately limited to **verbatim** quote\n * matching. The annotation's two selectors are written to agree (the\n * write-side `reconcileSelector` + `buildTextAnnotation` invariant\n * guarantee `content.substring(start, end) === exact`). At render time the\n * only legitimate discrepancy is *positional drift*: the document grew or\n * shrank above the span after the annotation was written, so the offset is\n * stale but the exact text still exists, byte-identical, elsewhere. That is\n * the W3C-intended role of `TextQuoteSelector`, and it is safe because it\n * demands identical text — no normalization, no fuzzy matching, no\n * judgment call.\n *\n * Anything that would require *fuzzy* recovery (smart-quote folding,\n * whitespace collapse, Levenshtein) is out of scope here: a non-verbatim\n * mismatch means the content representation diverged or the stored record\n * is wrong, both of which are deterministic and belong upstream (canonical\n * content, or a corrected annotation event). The renderer does not guess —\n * it renders at the stored offset and flags the anchor low-confidence so\n * the discrepancy surfaces for an upstream fix.\n *\n * Returns `null` only when nothing usable is present; otherwise always\n * returns a position with a `strategy` and `confidence`.\n */\n\nexport type AnchorStrategy =\n /** Position hint pointed exactly at the exact text. Unambiguous. */\n | 'fast-path'\n /** Exact text appears once verbatim in the content. No tiebreak needed. */\n | 'unique-occurrence'\n /** Multiple verbatim occurrences; prefix+suffix uniquely identified one. */\n | 'context-disambiguated'\n /** Multiple verbatim candidates; position closest to hint chosen. */\n | 'position-tiebreaker'\n /** Exact text not found verbatim (or no quote); raw stored offset used,\n * flagged for upstream correction. */\n | 'position-fallback';\n\nexport type AnchorConfidence = 'high' | 'medium' | 'low';\n\nexport interface RenderedAnchor {\n start: number;\n end: number;\n strategy: AnchorStrategy;\n confidence: AnchorConfidence;\n}\n\nexport interface AnchorSelectors {\n position?: { start: number; end: number };\n quote?: { exact: string; prefix?: string; suffix?: string };\n}\n\n/**\n * Distance window for the position tiebreaker. Candidates closer than this\n * to the hint receive a non-zero position score; further candidates fall\n * back to zero. Tuned for typical document sizes; calibration tests pin\n * the boundary behaviour rather than the exact value.\n */\nexport const POSITION_WINDOW = 1024;\n\n/**\n * Score weights — kept as named constants so the calibration tests can\n * import them and pin the *relationships* rather than the magnitudes.\n *\n * Invariant: a full-context match always outranks any position score.\n * (`CONTEXT_FULL_WEIGHT * 2 > POSITION_WEIGHT_MAX`, accounting for\n * prefix+suffix each contributing the full weight.)\n */\nexport const CONTEXT_FULL_WEIGHT = 10;\nexport const CONTEXT_PARTIAL_WEIGHT = 5;\nexport const POSITION_WEIGHT_MAX = 5;\n\n/**\n * Locate the best-effort anchor for an annotation against the content the\n * renderer is about to display. Verbatim-only — see the module doc.\n */\nexport function anchorAnnotation(\n content: string,\n selectors: AnchorSelectors,\n): RenderedAnchor | null {\n const { position, quote } = selectors;\n\n // No quote selector. Position is the only signal; use it verbatim if\n // present and in-range, otherwise the annotation has no anchor.\n if (!quote || !quote.exact) {\n if (!position) return null;\n if (position.start < 0 || position.end > content.length || position.start >= position.end) {\n return null;\n }\n return {\n start: position.start,\n end: position.end,\n strategy: 'position-fallback',\n confidence: 'low',\n };\n }\n\n const { exact, prefix, suffix } = quote;\n\n // Fast path: position hint exactly matches the exact text.\n if (position) {\n const probeEnd = position.start + exact.length;\n if (\n position.start >= 0 &&\n probeEnd <= content.length &&\n content.substring(position.start, probeEnd) === exact\n ) {\n return {\n start: position.start,\n end: probeEnd,\n strategy: 'fast-path',\n confidence: 'high',\n };\n }\n }\n\n // Find all occurrences via exact indexOf. Cheap; bounded by content\n // size; sufficient for the common case where the renderer's content\n // matches the worker's content character-for-character.\n const occurrences = findAllOccurrences(content, exact);\n\n if (occurrences.length === 1) {\n const start = occurrences[0]!;\n return {\n start,\n end: start + exact.length,\n strategy: 'unique-occurrence',\n confidence: 'high',\n };\n }\n\n if (occurrences.length > 1) {\n const winner = pickByScore(content, occurrences, exact, prefix, suffix, position?.start);\n return winner;\n }\n\n // No verbatim occurrence. We do NOT fuzzy-match at render time — a\n // non-verbatim mismatch means the content diverged or the record is\n // wrong, which is an upstream concern. Render at the stored offset so the\n // highlight still appears, flagged low-confidence so the discrepancy is\n // visible and gets corrected at the source.\n if (position && position.start >= 0 && position.end <= content.length && position.start < position.end) {\n return {\n start: position.start,\n end: position.end,\n strategy: 'position-fallback',\n confidence: 'low',\n };\n }\n\n return null;\n}\n\nfunction findAllOccurrences(content: string, exact: string): number[] {\n const out: number[] = [];\n let i = content.indexOf(exact);\n while (i !== -1) {\n out.push(i);\n i = content.indexOf(exact, i + 1);\n }\n return out;\n}\n\n/**\n * Context match score at a candidate offset.\n * Returns full / partial / no-match per side (prefix and suffix), then\n * sums each side weighted by `CONTEXT_FULL_WEIGHT` / `CONTEXT_PARTIAL_WEIGHT`.\n *\n * \"Full\" means the stored context aligns exactly with the source text\n * adjacent to the candidate. \"Partial\" is the looser substring check —\n * the stored context appears somewhere in the candidate's surroundings\n * but isn't anchored to the edges. This is the same partial-match logic\n * the previous `findTextWithContext` used, captured here so the scorer\n * can use it as one signal among many instead of a hard filter.\n */\nfunction contextScoreAt(\n content: string,\n pos: number,\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n): { score: number; full: boolean } {\n let score = 0;\n let prefixFull = true;\n let suffixFull = true;\n\n if (prefix) {\n const adj = content.substring(Math.max(0, pos - prefix.length), pos);\n if (adj.endsWith(prefix)) {\n score += CONTEXT_FULL_WEIGHT;\n prefixFull = true;\n } else if (adj.includes(prefix.trim()) && prefix.trim().length > 0) {\n score += CONTEXT_PARTIAL_WEIGHT;\n prefixFull = false;\n } else {\n prefixFull = false;\n }\n }\n\n if (suffix) {\n const adj = content.substring(pos + exact.length, Math.min(content.length, pos + exact.length + suffix.length));\n if (adj.startsWith(suffix)) {\n score += CONTEXT_FULL_WEIGHT;\n suffixFull = true;\n } else if (adj.includes(suffix.trim()) && suffix.trim().length > 0) {\n score += CONTEXT_PARTIAL_WEIGHT;\n suffixFull = false;\n } else {\n suffixFull = false;\n }\n }\n\n // \"Full\" overall match means every provided context field aligned\n // exactly — no partial fallbacks. Used to bump confidence to high.\n const full =\n (prefix === undefined || prefixFull) &&\n (suffix === undefined || suffixFull) &&\n (prefix !== undefined || suffix !== undefined);\n\n return { score, full };\n}\n\nfunction positionScoreAt(pos: number, hint: number | undefined): number {\n if (hint === undefined) return 0;\n const distance = Math.abs(pos - hint);\n if (distance >= POSITION_WINDOW) return 0;\n return POSITION_WEIGHT_MAX * (1 - distance / POSITION_WINDOW);\n}\n\nfunction pickByScore(\n content: string,\n occurrences: number[],\n exact: string,\n prefix: string | undefined,\n suffix: string | undefined,\n hint: number | undefined,\n): RenderedAnchor {\n let bestPos = occurrences[0]!;\n let bestScore = -1;\n let bestContextFull = false;\n let bestHasAnyContextSignal = false;\n let bestHasAnyPositionSignal = false;\n\n for (const pos of occurrences) {\n const ctx = contextScoreAt(content, pos, exact, prefix, suffix);\n const positionScore = positionScoreAt(pos, hint);\n const total = ctx.score + positionScore;\n if (total > bestScore) {\n bestScore = total;\n bestPos = pos;\n bestContextFull = ctx.full;\n bestHasAnyContextSignal = ctx.score > 0;\n bestHasAnyPositionSignal = positionScore > 0;\n }\n }\n\n // Strategy + confidence classification:\n // - both context fields aligned exactly → high-confidence context-disambiguated\n // - some context aligned (full or partial), no position needed → context-disambiguated, medium\n // - position broke the tie (winning candidate has position signal but no context signal,\n // or context was equal across candidates) → position-tiebreaker\n // - no signal at all (all candidates scored zero) → position-tiebreaker, low confidence,\n // deterministic first-of-many fallback\n let strategy: AnchorStrategy;\n let confidence: AnchorConfidence;\n\n if (bestContextFull) {\n strategy = 'context-disambiguated';\n confidence = 'high';\n } else if (bestHasAnyContextSignal && !bestHasAnyPositionSignal) {\n strategy = 'context-disambiguated';\n confidence = 'medium';\n } else if (bestHasAnyContextSignal && bestHasAnyPositionSignal) {\n // Context partially matched and position helped break the tie.\n strategy = 'position-tiebreaker';\n confidence = 'medium';\n } else if (bestHasAnyPositionSignal) {\n strategy = 'position-tiebreaker';\n confidence = 'medium';\n } else {\n strategy = 'position-tiebreaker';\n confidence = 'low';\n }\n\n return {\n start: bestPos,\n end: bestPos + exact.length,\n strategy,\n confidence,\n };\n}\n","/**\n * Locale information\n * Copied from SDK for frontend use\n */\n\nexport interface LocaleInfo {\n code: string;\n nativeName: string;\n englishName: string;\n}\n\nexport const LOCALES: readonly LocaleInfo[] = [\n { code: 'ar', nativeName: 'العربية', englishName: 'Arabic' },\n { code: 'bn', nativeName: 'বাংলা', englishName: 'Bengali' },\n { code: 'cs', nativeName: 'Čeština', englishName: 'Czech' },\n { code: 'da', nativeName: 'Dansk', englishName: 'Danish' },\n { code: 'de', nativeName: 'Deutsch', englishName: 'German' },\n { code: 'el', nativeName: 'Ελληνικά', englishName: 'Greek' },\n { code: 'en', nativeName: 'English', englishName: 'English' },\n { code: 'es', nativeName: 'Español', englishName: 'Spanish' },\n { code: 'fa', nativeName: 'فارسی', englishName: 'Persian' },\n { code: 'fi', nativeName: 'Suomi', englishName: 'Finnish' },\n { code: 'fr', nativeName: 'Français', englishName: 'French' },\n { code: 'he', nativeName: 'עברית', englishName: 'Hebrew' },\n { code: 'hi', nativeName: 'हिन्दी', englishName: 'Hindi' },\n { code: 'id', nativeName: 'Bahasa Indonesia', englishName: 'Indonesian' },\n { code: 'it', nativeName: 'Italiano', englishName: 'Italian' },\n { code: 'ja', nativeName: '日本語', englishName: 'Japanese' },\n { code: 'ko', nativeName: '한국어', englishName: 'Korean' },\n { code: 'ms', nativeName: 'Bahasa Melayu', englishName: 'Malay' },\n { code: 'nl', nativeName: 'Nederlands', englishName: 'Dutch' },\n { code: 'no', nativeName: 'Norsk', englishName: 'Norwegian' },\n { code: 'pl', nativeName: 'Polski', englishName: 'Polish' },\n { code: 'pt', nativeName: 'Português', englishName: 'Portuguese' },\n { code: 'ro', nativeName: 'Română', englishName: 'Romanian' },\n { code: 'sv', nativeName: 'Svenska', englishName: 'Swedish' },\n { code: 'th', nativeName: 'ไทย', englishName: 'Thai' },\n { code: 'tr', nativeName: 'Türkçe', englishName: 'Turkish' },\n { code: 'uk', nativeName: 'Українська', englishName: 'Ukrainian' },\n { code: 'vi', nativeName: 'Tiếng Việt', englishName: 'Vietnamese' },\n { code: 'zh', nativeName: '中文', englishName: 'Chinese' },\n] as const;\n\n// Create lookup map for efficient access\nconst localeByCode = new Map<string, LocaleInfo>(\n LOCALES.map(locale => [locale.code.toLowerCase(), locale])\n);\n\n/**\n * Get locale information by code\n */\nexport function getLocaleInfo(code: string | undefined): LocaleInfo | undefined {\n if (!code) return undefined;\n return localeByCode.get(code.toLowerCase());\n}\n\n/**\n * Get the native name of a language by its locale code\n */\nexport function getLocaleNativeName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.nativeName;\n}\n\n/**\n * Get the English name of a language by its locale code\n */\nexport function getLocaleEnglishName(code: string | undefined): string | undefined {\n return getLocaleInfo(code)?.englishName;\n}\n\n/**\n * Format locale code for display as \"Native Name (code)\"\n */\nexport function formatLocaleDisplay(code: string | undefined): string | undefined {\n if (!code) return undefined;\n\n const info = getLocaleInfo(code);\n if (!info) return code;\n\n return `${info.nativeName} (${code.toLowerCase()})`;\n}\n\n/**\n * Get all supported locale codes\n */\nexport function getAllLocaleCodes(): readonly string[] {\n return LOCALES.map(l => l.code);\n}\n","/**\n * SVG Utility Functions\n *\n * Utilities for creating, parsing, and manipulating W3C-compliant SVG selectors\n * for image annotation.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface BoundingBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Create W3C-compliant SVG rectangle selector\n */\nexport function createRectangleSvg(start: Point, end: Point): string {\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const width = Math.abs(end.x - start.x);\n const height = Math.abs(end.y - start.y);\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG polygon selector\n */\nexport function createPolygonSvg(points: Point[]): string {\n if (points.length < 3) {\n throw new Error('Polygon requires at least 3 points');\n }\n\n const pointsStr = points.map(p => `${p.x},${p.y}`).join(' ');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><polygon points=\"${pointsStr}\"/></svg>`;\n}\n\n/**\n * Create W3C-compliant SVG circle selector\n */\nexport function createCircleSvg(center: Point, radius: number): string {\n if (radius <= 0) {\n throw new Error('Circle radius must be positive');\n }\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"${center.x}\" cy=\"${center.y}\" r=\"${radius}\"/></svg>`;\n}\n\n/**\n * Parse SVG selector to extract shape type and data\n */\nexport function parseSvgSelector(svg: string): {\n type: 'rect' | 'polygon' | 'circle' | 'path';\n data: any;\n} | null {\n // Extract rectangle\n const rectMatch = svg.match(/<rect\\s+([^>]+)\\/>/);\n if (rectMatch && rectMatch[1]) {\n const attrs = rectMatch[1];\n const x = parseFloat(attrs.match(/x=\"([^\"]+)\"/)?.[1] || '0');\n const y = parseFloat(attrs.match(/y=\"([^\"]+)\"/)?.[1] || '0');\n const width = parseFloat(attrs.match(/width=\"([^\"]+)\"/)?.[1] || '0');\n const height = parseFloat(attrs.match(/height=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'rect',\n data: { x, y, width, height }\n };\n }\n\n // Extract polygon\n const polygonMatch = svg.match(/<polygon\\s+points=\"([^\"]+)\"/);\n if (polygonMatch && polygonMatch[1]) {\n const pointsStr = polygonMatch[1];\n const points = pointsStr.split(/\\s+/).map(pair => {\n const [x, y] = pair.split(',').map(parseFloat);\n return { x, y };\n });\n\n return {\n type: 'polygon',\n data: { points }\n };\n }\n\n // Extract circle\n const circleMatch = svg.match(/<circle\\s+([^>]+)\\/>/);\n if (circleMatch && circleMatch[1]) {\n const attrs = circleMatch[1];\n const cx = parseFloat(attrs.match(/cx=\"([^\"]+)\"/)?.[1] || '0');\n const cy = parseFloat(attrs.match(/cy=\"([^\"]+)\"/)?.[1] || '0');\n const r = parseFloat(attrs.match(/r=\"([^\"]+)\"/)?.[1] || '0');\n\n return {\n type: 'circle',\n data: { cx, cy, r }\n };\n }\n\n return null;\n}\n\n/**\n * Normalize coordinates from display space to image native resolution\n */\nexport function normalizeCoordinates(\n point: Point,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): Point {\n return {\n x: (point.x / displayWidth) * imageWidth,\n y: (point.y / displayHeight) * imageHeight\n };\n}\n\n/**\n * Scale entire SVG selector from display space to image native resolution\n */\nexport function scaleSvgToNative(\n svg: string,\n displayWidth: number,\n displayHeight: number,\n imageWidth: number,\n imageHeight: number\n): string {\n const parsed = parseSvgSelector(svg);\n if (!parsed) return svg;\n\n const scaleX = imageWidth / displayWidth;\n const scaleY = imageHeight / displayHeight;\n\n switch (parsed.type) {\n case 'rect': {\n const { x, y, width, height } = parsed.data;\n return createRectangleSvg(\n { x: x * scaleX, y: y * scaleY },\n { x: (x + width) * scaleX, y: (y + height) * scaleY }\n );\n }\n\n case 'circle': {\n const { cx, cy, r } = parsed.data;\n return createCircleSvg(\n { x: cx * scaleX, y: cy * scaleY },\n r * Math.min(scaleX, scaleY)\n );\n }\n\n case 'polygon': {\n const points = parsed.data.points.map((p: Point) => ({\n x: p.x * scaleX,\n y: p.y * scaleY\n }));\n return createPolygonSvg(points);\n }\n }\n\n return svg;\n}\n","/**\n * Selector reconciliation for write-time annotation construction.\n *\n * LLM-produced text offsets are guides, not authoritative anchors.\n * `reconcileSelector` takes whatever the LLM emitted and produces a\n * `TextQuoteSelector`-equivalent `start`/`end`/`exact`/`prefix`/`suffix`\n * that is provably consistent with the source content:\n *\n * - `content.substring(start, end) === exact`\n * - `content.substring(start - prefix.length, start) === prefix`\n * - `content.substring(end, end + suffix.length) === suffix`\n *\n * No caller spreads LLM-emitted prefix/suffix into the stored selector.\n * The shared helper extracts both from source at the corrected position,\n * so the no-overlap invariant holds by construction.\n *\n * Returns `null` when the LLM emitted text that doesn't appear in the\n * source. Callers filter; the helper doesn't decide for them.\n *\n * @see https://www.w3.org/TR/annotation-model/#text-quote-selector\n */\n\nimport { findBestTextMatch, buildContentCache, type MatchQuality } from './fuzzy-anchor';\n\n/**\n * How the reconciliation arrived at the chosen offset. Carried into the\n * worker log so operators can audit ambiguous matches; the\n * `first-of-many` flag, in particular, is the signal that an annotation\n * *may* be anchored at the wrong occurrence and warrants review.\n */\nexport type AnchorMethod =\n /** Exact text appears once in the source — anchored unambiguously. */\n | 'unique-match'\n /** Multiple occurrences; LLM-emitted prefix/suffix picked one. */\n | 'context-recovered'\n /** Exact text not found verbatim; fuzzy match recovered it. */\n | 'fuzzy-match'\n /** Multiple occurrences, no context disambiguated — risky fallback. */\n | 'first-of-many';\n\nexport interface ReconciledSelector {\n start: number;\n end: number;\n /** Always a substring of the source content — never the LLM's emission. */\n exact: string;\n /** Extracted from source via extractContext — never the LLM's emission. */\n prefix?: string;\n /** Extracted from source via extractContext — never the LLM's emission. */\n suffix?: string;\n anchorMethod: AnchorMethod;\n /** Present when the fuzzy fallback recovered the match, naming how. */\n matchQuality?: MatchQuality;\n}\n\nexport interface LlmSelectorInput {\n exact: string;\n /** LLM-emitted context for disambiguation only — not for storage. */\n prefix?: string;\n /** LLM-emitted context for disambiguation only — not for storage. */\n suffix?: string;\n}\n\nconst CONTEXT_LENGTH = 64;\nconst MAX_EXTENSION = 32;\n// Minimum window of source text compared against an LLM-emitted prefix/suffix\n// when disambiguating multiple occurrences. The actual window grows to the\n// length of the LLM's prefix/suffix when that's longer — the prompts invite\n// up to 64 chars, and a fixed 32-char window can't `endsWith`/`includes` a\n// 64-char string, which would silently defeat disambiguation for exactly the\n// long, distinctive contexts that disambiguate best.\nconst DISAMBIGUATION_MIN_WINDOW = 32;\n\n/**\n * Extract prefix and suffix context for a `TextQuoteSelector` from\n * source content. Used internally by `reconcileSelector` after offsets\n * are reconciled, and exported for callers (e.g. UI-side selection\n * capture) that need the same extraction semantics.\n *\n * Extracts up to 64 characters before and after the selected text,\n * extending up to 32 additional chars to reach a word boundary so the\n * prefix/suffix is meaningful context rather than mid-word fragments.\n */\nexport function extractContext(\n content: string,\n start: number,\n end: number,\n): { prefix?: string; suffix?: string } {\n const result: { prefix?: string; suffix?: string } = {};\n\n if (start > 0) {\n let prefixStart = Math.max(0, start - CONTEXT_LENGTH);\n let extensionCount = 0;\n while (prefixStart > 0 && extensionCount < MAX_EXTENSION) {\n const char = content[prefixStart - 1];\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) break;\n prefixStart--;\n extensionCount++;\n }\n result.prefix = content.substring(prefixStart, start);\n }\n\n if (end < content.length) {\n let suffixEnd = Math.min(content.length, end + CONTEXT_LENGTH);\n let extensionCount = 0;\n while (suffixEnd < content.length && extensionCount < MAX_EXTENSION) {\n const char = content[suffixEnd];\n if (!char || /[\\s.,;:!?'\"()\\[\\]{}<>\\/\\\\]/.test(char)) break;\n suffixEnd++;\n extensionCount++;\n }\n result.suffix = content.substring(end, suffixEnd);\n }\n\n return result;\n}\n\n/**\n * Reconcile LLM-emitted offsets against the source. Returns a selector\n * whose `start`/`end` are verified to bracket `exact` in `content`, and\n * whose `prefix`/`suffix` are extracted from source — never carried\n * verbatim from the LLM.\n *\n * Returns `null` if `exact` cannot be found anywhere in the content,\n * even via fuzzy match. Callers filter null and log the drop.\n */\nexport function reconcileSelector(\n content: string,\n llm: LlmSelectorInput,\n): ReconciledSelector | null {\n const { exact, prefix: llmPrefix, suffix: llmSuffix } = llm;\n if (!exact) return null;\n\n // Find all verbatim occurrences.\n const occurrences: number[] = [];\n let i = content.indexOf(exact);\n while (i !== -1) {\n occurrences.push(i);\n i = content.indexOf(exact, i + 1);\n }\n\n if (occurrences.length === 1) {\n const start = occurrences[0]!;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'unique-match',\n };\n }\n\n if (occurrences.length > 1) {\n // Disambiguate via LLM-emitted prefix/suffix when present. Size the\n // comparison window to the LLM's prefix/suffix (with a floor), so a\n // 64-char prefix is matched against ≥64 chars of source — a fixed\n // smaller window can't `endsWith`/`includes` a longer LLM string.\n if (llmPrefix || llmSuffix) {\n const prefixWindow = Math.max(DISAMBIGUATION_MIN_WINDOW, llmPrefix?.length ?? 0);\n const suffixWindow = Math.max(DISAMBIGUATION_MIN_WINDOW, llmSuffix?.length ?? 0);\n for (const pos of occurrences) {\n const candPrefix = content.substring(Math.max(0, pos - prefixWindow), pos);\n const candSuffix = content.substring(\n pos + exact.length,\n Math.min(content.length, pos + exact.length + suffixWindow),\n );\n const prefixOk = !llmPrefix || candPrefix.endsWith(llmPrefix) || candPrefix.includes(llmPrefix.trim());\n const suffixOk = !llmSuffix || candSuffix.startsWith(llmSuffix) || candSuffix.includes(llmSuffix.trim());\n if (prefixOk && suffixOk) {\n const start = pos;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'context-recovered',\n };\n }\n }\n }\n\n // No context match. Fall back to the first occurrence and flag for\n // audit. Without an LLM-emitted locality hint there's no better\n // signal at this stage; `first-of-many` callers should log loudly so\n // operators can correct misanchored annotations.\n const start = occurrences[0]!;\n const end = start + exact.length;\n const ctx = extractContext(content, start, end);\n return {\n start,\n end,\n exact,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'first-of-many',\n };\n }\n\n // No verbatim occurrences. Try fuzzy match (case-insensitive,\n // whitespace-normalized, Levenshtein with 5% tolerance). No position\n // hint to bias the search — fuzzy match scans content globally.\n const cache = buildContentCache(content);\n const fuzzy = findBestTextMatch(content, exact, undefined, cache);\n if (!fuzzy) return null;\n\n const actual = content.substring(fuzzy.start, fuzzy.end);\n const ctx = extractContext(content, fuzzy.start, fuzzy.end);\n return {\n start: fuzzy.start,\n end: fuzzy.end,\n // Use the actual source text, not the LLM's version — the LLM may\n // have emitted slightly different characters (smart vs straight\n // quotes, etc.) and we store what's verifiable.\n exact: actual,\n ...(ctx.prefix !== undefined ? { prefix: ctx.prefix } : {}),\n ...(ctx.suffix !== undefined ? { suffix: ctx.suffix } : {}),\n anchorMethod: 'fuzzy-match',\n matchQuality: fuzzy.matchQuality,\n };\n}\n","/**\n * Text encoding utilities for consistent charset handling\n *\n * Ensures frontend decoding matches backend decoding by respecting\n * charset parameters in mediaType (e.g., \"text/plain; charset=iso-8859-1\")\n */\n\n/**\n * Extract charset from mediaType parameter\n *\n * @param mediaType - Media type with optional charset (e.g., \"text/plain; charset=utf-8\")\n * @returns Charset name in lowercase (defaults to \"utf-8\")\n *\n * @example\n * extractCharset(\"text/plain; charset=iso-8859-1\") // \"iso-8859-1\"\n * extractCharset(\"text/plain\") // \"utf-8\"\n */\nexport function extractCharset(mediaType: string): string {\n const charsetMatch = mediaType.match(/charset=([^\\s;]+)/i);\n return (charsetMatch?.[1] || 'utf-8').toLowerCase();\n}\n\n/**\n * Decode ArrayBuffer to string using charset from mediaType\n *\n * Uses TextDecoder with the charset extracted from mediaType parameter.\n * This ensures the same character space is used for both annotation creation\n * (backend) and rendering (frontend).\n *\n * @param buffer - Binary data to decode\n * @param mediaType - Media type with optional charset parameter\n * @returns Decoded string in the original character space\n *\n * @example\n * const buffer = new Uint8Array([...]);\n * const text = decodeWithCharset(buffer, \"text/plain; charset=iso-8859-1\");\n */\nexport function decodeWithCharset(buffer: ArrayBuffer, mediaType: string): string {\n const charset = extractCharset(mediaType);\n\n // TextDecoder supports standard charset names\n // Common mappings that work in browsers:\n // - utf-8, utf-16, utf-16le, utf-16be\n // - iso-8859-1 through iso-8859-15\n // - windows-1252, windows-1251, etc.\n const decoder = new TextDecoder(charset);\n return decoder.decode(buffer);\n}\n","/**\n * Generic validation utilities for @semiont/http-transport\n *\n * Pure TypeScript validation with no external dependencies.\n * Safe to use in any JavaScript environment (Node.js, browser, Deno, etc.)\n */\n\n/**\n * Validation result types\n */\nexport type ValidationSuccess<T> = { success: true; data: T };\nexport type ValidationFailure = { success: false; error: string; details?: string[] };\nexport type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;\n\n/**\n * JWT Token validation\n *\n * Validates JWT token format (header.payload.signature).\n * Does not verify signature - use for format validation only.\n */\nexport const JWTTokenSchema = {\n parse(token: unknown): string {\n if (typeof token !== 'string') {\n throw new Error('Token must be a string');\n }\n if (!token || token.length === 0) {\n throw new Error('Token is required');\n }\n // JWT format: header.payload.signature\n const jwtRegex = /^[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]*$/;\n if (!jwtRegex.test(token)) {\n throw new Error('Invalid JWT token format');\n }\n return token;\n },\n\n safeParse(token: unknown): ValidationResult<string> {\n try {\n const validated = this.parse(token);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Invalid JWT token',\n };\n }\n },\n};\n\n/**\n * Generic validation helper with error formatting\n *\n * Wraps any schema's parse method with try/catch and returns ValidationResult.\n *\n * @example\n * ```typescript\n * const result = validateData(JWTTokenSchema, 'eyJ...');\n * if (result.success) {\n * console.log('Valid token:', result.data);\n * } else {\n * console.error('Invalid:', result.error);\n * }\n * ```\n */\nexport function validateData<T>(\n schema: { parse(data: unknown): T },\n data: unknown\n): ValidationResult<T> {\n try {\n const validated = schema.parse(data);\n return { success: true, data: validated };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Email validation helper\n *\n * Validates email format using RFC 5322 simplified regex.\n *\n * @param email - Email address to validate\n * @returns true if valid email format\n */\nexport function isValidEmail(email: string): boolean {\n if (email.length < 1 || email.length > 255) {\n return false;\n }\n // RFC 5322 simplified email regex\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n}\n","/**\n * Media-type registry for Semiont\n *\n * One supported-types list, capability-tiered, keyed by the spec's\n * SupportedMediaType enum. Admission (registry membership) is the\n * create/yield gate: every member is storable, nameable, and uploadable.\n * The curated capabilities say what more the system can do with a type:\n *\n * - `render` — which viewer the UI mounts ('none' → metadata + download)\n * - `anchoring` — which annotation model applies: character-offset text\n * selectors vs spatial geometry (PDFs are spatial)\n * - `extractText` — how the Smelter gets embeddable text ('none' → skip\n * embedding, never mojibake)\n * - `authorable` — offered in the compose editor's format dropdown\n * - `uploadable` — big tent: true for every registry member\n *\n * Capabilities are orthogonal strategies, not a ladder: images render but\n * yield no text; PDFs yield text but aren't authorable. A \"tier\" is a\n * derived reading, not a stored fact.\n *\n * Import-leniency invariant: restore/import preserves archive mediaTypes\n * verbatim, so \"every stored mediaType is registry-valid\" holds only for\n * content that entered through the validated create/yield gate. No code\n * reading a stored mediaType may assume `capabilitiesOf()` succeeds — the\n * `undefined` branch is mandatory wherever stored types are read.\n */\n\nimport type { components } from './types';\n\nexport type SupportedMediaType = components['schemas']['SupportedMediaType'];\n\nexport type RenderMode = 'text' | 'image' | 'pdf' | 'none';\nexport type AnchoringModel = 'text-selector' | 'spatial' | 'none';\nexport type TextExtraction = 'decode' | 'pdf-text-layer' | 'none';\n\nexport interface MediaTypeCapabilities {\n /** Canonical file extension, with leading dot. */\n extension: `.${string}`;\n /** UI display name. */\n label: string;\n render: RenderMode;\n anchoring: AnchoringModel;\n extractText: TextExtraction;\n authorable: boolean;\n uploadable: boolean;\n /** Whether the generation worker can produce this type as a yield artifact.\n * Gate for `outputMediaType` — unsupported requests fail loudly, never\n * fall back to markdown under a mislabeled format. */\n generatable: boolean;\n}\n\n/** Storage tier: catalogued — stored, named, uploadable — but not\n * displayed or annotated. */\nconst storedBinary = (extension: `.${string}`, label: string): MediaTypeCapabilities => ({\n extension,\n label,\n render: 'none',\n anchoring: 'none',\n extractText: 'none',\n authorable: false,\n uploadable: true,\n generatable: false,\n});\n\n/** Storage tier, text-flavored: embedded (charset-aware decode), not rendered. */\nconst storedText = (extension: `.${string}`, label: string): MediaTypeCapabilities => ({\n ...storedBinary(extension, label),\n extractText: 'decode',\n});\n\n/**\n * The registry. `satisfies Record<SupportedMediaType, …>` is the\n * drift-lock: adding a type to the spec enum without a capabilities row\n * (or vice versa) is a compile error.\n *\n * Row order matters for `mediaTypeForExtension`: extension collisions\n * (.xml, .yaml, .js, .ts, .webm) resolve to the first row declaring the\n * extension.\n */\nexport const MEDIA_TYPES = {\n // Full-capability tier\n // `generatable: application/pdf` — the Typst renderer (PDF-GENERATION P3):\n // the model writes Typst, the worker's pinned binary compiles it.\n 'text/markdown': { extension: '.md', label: 'Markdown', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: true },\n 'text/plain': { extension: '.txt', label: 'Plain Text', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: true },\n 'text/html': { extension: '.html', label: 'HTML', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: true, uploadable: true, generatable: false },\n 'application/json': { extension: '.json', label: 'JSON', render: 'text', anchoring: 'text-selector', extractText: 'decode', authorable: false, uploadable: true, generatable: false },\n 'image/png': { extension: '.png', label: 'PNG image', render: 'image', anchoring: 'spatial', extractText: 'none', authorable: false, uploadable: true, generatable: false },\n 'image/jpeg': { extension: '.jpg', label: 'JPEG image', render: 'image', anchoring: 'spatial', extractText: 'none', authorable: false, uploadable: true, generatable: false },\n 'application/pdf': { extension: '.pdf', label: 'PDF', render: 'pdf', anchoring: 'spatial', extractText: 'pdf-text-layer', authorable: false, uploadable: true, generatable: true },\n\n // Storage tier — the big tent. Every row is a deliberate admission,\n // promotable by editing its row. Text-flavored rows embed (decode).\n\n // Text\n 'text/css': storedText('.css', 'CSS'),\n 'text/csv': storedText('.csv', 'CSV'),\n 'text/xml': storedText('.xml', 'XML'),\n\n // Structured-text application formats\n 'application/xml': storedText('.xml', 'XML'),\n 'application/yaml': storedText('.yaml', 'YAML'),\n 'application/x-yaml': storedText('.yaml', 'YAML'),\n\n // Programming languages\n 'text/javascript': storedText('.js', 'JavaScript'),\n 'application/javascript': storedText('.js', 'JavaScript'),\n 'text/x-typescript': storedText('.ts', 'TypeScript'),\n 'application/typescript': storedText('.ts', 'TypeScript'),\n 'text/x-python': storedText('.py', 'Python source'),\n 'text/x-java': storedText('.java', 'Java source'),\n 'text/x-c': storedText('.c', 'C source'),\n 'text/x-c++': storedText('.cpp', 'C++ source'),\n 'text/x-csharp': storedText('.cs', 'C# source'),\n 'text/x-go': storedText('.go', 'Go source'),\n 'text/x-rust': storedText('.rs', 'Rust source'),\n 'text/x-ruby': storedText('.rb', 'Ruby source'),\n 'text/x-php': storedText('.php', 'PHP source'),\n 'text/x-swift': storedText('.swift', 'Swift source'),\n 'text/x-kotlin': storedText('.kt', 'Kotlin source'),\n 'text/x-shell': storedText('.sh', 'Shell script'),\n\n // Documents\n 'application/msword': storedBinary('.doc', 'Word document (legacy)'),\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': storedBinary('.docx', 'Word document'),\n 'application/vnd.ms-excel': storedBinary('.xls', 'Excel spreadsheet (legacy)'),\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': storedBinary('.xlsx', 'Excel spreadsheet'),\n 'application/vnd.ms-powerpoint': storedBinary('.ppt', 'PowerPoint presentation (legacy)'),\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': storedBinary('.pptx', 'PowerPoint presentation'),\n\n // Archives\n 'application/zip': storedBinary('.zip', 'ZIP archive'),\n 'application/gzip': storedBinary('.gz', 'Gzip archive'),\n 'application/x-tar': storedBinary('.tar', 'TAR archive'),\n 'application/x-7z-compressed': storedBinary('.7z', '7z archive'),\n\n // Binaries\n 'application/octet-stream': storedBinary('.bin', 'Binary'),\n 'application/wasm': storedBinary('.wasm', 'WebAssembly module'),\n\n // Images beyond the rendered pair\n 'image/gif': storedBinary('.gif', 'GIF image'),\n 'image/webp': storedBinary('.webp', 'WebP image'),\n 'image/svg+xml': storedBinary('.svg', 'SVG image'),\n 'image/bmp': storedBinary('.bmp', 'BMP image'),\n 'image/tiff': storedBinary('.tiff', 'TIFF image'),\n 'image/x-icon': storedBinary('.ico', 'Icon'),\n\n // Video (before audio so .webm resolves to video)\n 'video/mp4': storedBinary('.mp4', 'MP4 video'),\n 'video/mpeg': storedBinary('.mpeg', 'MPEG video'),\n 'video/webm': storedBinary('.webm', 'WebM video'),\n 'video/ogg': storedBinary('.ogv', 'Ogg video'),\n 'video/quicktime': storedBinary('.mov', 'QuickTime video'),\n 'video/x-msvideo': storedBinary('.avi', 'AVI video'),\n\n // Audio\n 'audio/mpeg': storedBinary('.mp3', 'MP3 audio'),\n 'audio/wav': storedBinary('.wav', 'WAV audio'),\n 'audio/ogg': storedBinary('.ogg', 'Ogg audio'),\n 'audio/webm': storedBinary('.webm', 'WebM audio'),\n 'audio/aac': storedBinary('.aac', 'AAC audio'),\n 'audio/flac': storedBinary('.flac', 'FLAC audio'),\n\n // Fonts\n 'font/woff': storedBinary('.woff', 'WOFF font'),\n 'font/woff2': storedBinary('.woff2', 'WOFF2 font'),\n 'font/ttf': storedBinary('.ttf', 'TrueType font'),\n 'font/otf': storedBinary('.otf', 'OpenType font'),\n} satisfies Record<SupportedMediaType, MediaTypeCapabilities>;\n\n// String-indexable view for lookups with runtime strings.\nconst REGISTRY: Readonly<Record<string, MediaTypeCapabilities>> = MEDIA_TYPES;\n\n/**\n * Strip parameters (\"; charset=...\") and normalize case.\n * Replaces the inline `split(';')[0]` sites across the codebase.\n */\nexport function baseMediaType(format: string): string {\n return format.split(';')[0]!.trim().toLowerCase();\n}\n\n/**\n * Registry membership — the admission gate. Exact match: callers pass a\n * base type (see `baseMediaType`); strings carrying parameters are not\n * members.\n */\nexport function isSupportedMediaType(format: string): format is SupportedMediaType {\n return Object.hasOwn(MEDIA_TYPES, format);\n}\n\n/** Capabilities for a format (parameters tolerated), or undefined on registry miss. */\nexport function capabilitiesOf(format: string): MediaTypeCapabilities | undefined {\n return REGISTRY[baseMediaType(format)];\n}\n\n/**\n * Lenient extension lookup for naming foreign/imported content: '.dat' on\n * registry miss. Exporters use this — a vocabulary change must never\n * refuse to name restored data.\n */\nexport function extensionForMediaType(format: string): string {\n return capabilitiesOf(format)?.extension ?? '.dat';\n}\n\nconst EXTENSION_TO_MEDIA_TYPE: ReadonlyMap<string, SupportedMediaType> = (() => {\n const map = new Map<string, SupportedMediaType>();\n for (const type of Object.keys(MEDIA_TYPES) as SupportedMediaType[]) {\n const ext = MEDIA_TYPES[type].extension;\n if (!map.has(ext)) map.set(ext, type);\n }\n return map;\n})();\n\n/** Alternate spellings accepted by `mediaTypeForExtension`, mapped to\n * canonical registry extensions. */\nconst EXTENSION_ALIASES: Readonly<Record<string, string>> = {\n '.markdown': '.md',\n '.htm': '.html',\n '.jpeg': '.jpg',\n '.yml': '.yaml',\n};\n\n/**\n * Inverted registry: extension → media type, for the CLI and the upload\n * detection chain. Accepts 'md' or '.md', any case, and common alternate\n * spellings. Returns undefined for unknown extensions — detection chains\n * fall back to 'application/octet-stream' themselves.\n */\nexport function mediaTypeForExtension(ext: string): SupportedMediaType | undefined {\n const lower = ext.trim().toLowerCase();\n const dotted = lower.startsWith('.') ? lower : `.${lower}`;\n return EXTENSION_TO_MEDIA_TYPE.get(EXTENSION_ALIASES[dotted] ?? dotted);\n}\n\n/**\n * The Smelter's gate: how to get embeddable text from a format. Registry\n * rows answer directly; on a registry miss, base types under text/* decode\n * (RFC 2046 guarantees the text top-level type is textual — imported\n * unregistered text subtypes embed too), everything else is 'none'.\n */\nexport function textExtractionOf(format: string): TextExtraction {\n const caps = capabilitiesOf(format);\n if (caps) return caps.extractText;\n return baseMediaType(format).startsWith('text/') ? 'decode' : 'none';\n}\n\nconst REGISTRY_KEYS = Object.keys(MEDIA_TYPES) as SupportedMediaType[];\n\n/** Types offered in the compose editor's format dropdown. */\nexport const AUTHORABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].authorable,\n);\n\n/** Registry rows whose text the Smelter can extract. Rows only — the\n * text/* fallback in `textExtractionOf` isn't enumerable. */\nexport const EMBEDDABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].extractText !== 'none',\n);\n\n/** Types the generation worker can produce as a yield artifact — the\n * `outputMediaType` gate reads this, not a local table. */\nexport const GENERATABLE_MEDIA_TYPES: readonly SupportedMediaType[] = REGISTRY_KEYS.filter(\n (type) => MEDIA_TYPES[type].generatable,\n);\n","/**\n * Text Chunking Utilities\n *\n * Splits long text into overlapping chunks for embedding.\n * Each chunk is a passage that fits within the embedding model's context window.\n */\n\nexport interface ChunkingConfig {\n chunkSize: number; // approximate tokens per chunk\n overlap: number; // tokens of overlap between adjacent chunks\n}\n\nexport const DEFAULT_CHUNKING_CONFIG: ChunkingConfig = {\n chunkSize: 512,\n overlap: 64,\n};\n\n/**\n * Rough token count estimate: ~4 characters per token for English text.\n *\n * Exported as the single token-estimation heuristic: `chunkText` sizes chunks\n * with it, and inference/detection budget arithmetic must use the same\n * heuristic so estimates and chunk sizes agree.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Split text into overlapping chunks.\n *\n * Splits on paragraph boundaries when possible, falling back to sentence\n * boundaries, then word boundaries. Each chunk overlaps with the previous\n * by `overlap` tokens worth of text.\n */\nexport function chunkText(text: string, config: ChunkingConfig = DEFAULT_CHUNKING_CONFIG): string[] {\n if (text.length === 0) return [];\n const totalTokens = estimateTokens(text);\n if (totalTokens <= config.chunkSize) {\n return [text];\n }\n\n const chunkChars = config.chunkSize * 4;\n const overlapChars = config.overlap * 4;\n const chunks: string[] = [];\n let start = 0;\n\n while (start < text.length) {\n let end = Math.min(start + chunkChars, text.length);\n\n // Try to break at a paragraph boundary\n if (end < text.length) {\n const paraBreak = text.lastIndexOf('\\n\\n', end);\n if (paraBreak > start + chunkChars / 2) {\n end = paraBreak;\n } else {\n // Try sentence boundary\n const sentenceBreak = text.lastIndexOf('. ', end);\n if (sentenceBreak > start + chunkChars / 2) {\n end = sentenceBreak + 1;\n } else {\n // Try word boundary\n const wordBreak = text.lastIndexOf(' ', end);\n if (wordBreak > start + chunkChars / 2) {\n end = wordBreak;\n }\n }\n }\n }\n\n chunks.push(text.slice(start, end).trim());\n const nextStart = end - overlapChars;\n start = nextStart > start ? nextStart : end;\n if (start >= text.length) break;\n }\n\n return chunks.filter(c => c.length > 0);\n}\n","/**\n * Common type guard utilities\n */\n\n/**\n * Check if value is a string\n */\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\n/**\n * Check if value is a number (not NaN)\n */\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value);\n}\n\n/**\n * Check if value is an object (not null, not array)\n */\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Check if value is an array\n */\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\n/**\n * Check if value is a boolean\n */\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\n/**\n * Check if value is a function\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === 'function';\n}\n\n/**\n * Check if value is null\n */\nexport function isNull(value: unknown): value is null {\n return value === null;\n}\n\n/**\n * Check if value is undefined\n */\nexport function isUndefined(value: unknown): value is undefined {\n return value === undefined;\n}\n\n/**\n * Check if value is null or undefined\n */\nexport function isNullish(value: unknown): value is null | undefined {\n return value === null || value === undefined;\n}\n\n/**\n * Check if value is defined (not null or undefined)\n */\nexport function isDefined<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\n/**\n * Boundary guard for `job:create` generation params (YIELD-FROM-CONTEXT P1).\n *\n * Checks the REQUIRED trio the schema declares (`title`, `storageUri`,\n * `context`) plus basic shape — deliberately NOT a full schema validation\n * (that depth belongs to the spec and its generated types); this is the\n * runtime half of the contract for values whose type history was severed:\n * wire JSON, storage, casts. For well-typed callers it is dead code, and\n * that is the correct price for a trust-boundary check.\n */\nexport function isGenerationJobParams(\n value: unknown,\n): value is import('./payload-types').GenerationJobParams {\n if (!isObject(value)) return false;\n return (\n typeof value.title === 'string'\n && typeof value.storageUri === 'string'\n && isObject(value.context)\n );\n}\n\n/**\n * Boundary guard for a `GatheredContext` whose type history was severed —\n * today that is exactly one place: the wizard stashes the context in\n * `sessionStorage` on the way to the compose page, which reads it back and\n * `JSON.parse`s it.\n *\n * Checks what consumers actually dereference rather than the whole schema:\n * `focus` (every view branches on `focus.kind`) and `graph.nodes` / `graph.edges`,\n * which `deriveViews` maps over without a guard. Both are `required` in\n * `GatheredContext.json` / `KnowledgeGraph.json`, so this is dead code for every\n * well-typed caller — the price of a trust boundary, same as\n * `isGenerationJobParams` above.\n *\n * The failure it prevents is not cosmetic: `deriveViews` runs during render, so a\n * stale stash (a tab held open across a deploy) throws inside React rather than\n * degrading, unmounting the flow to the nearest error boundary.\n */\nexport function isGatheredContext(\n value: unknown,\n): value is import('./payload-types').GatheredContext {\n if (!isObject(value)) return false;\n if (!isObject(value.focus)) return false;\n if (!isObject(value.graph)) return false;\n return isArray(value.graph.nodes) && isArray(value.graph.edges);\n}\n","/**\n * DID (Decentralized Identifier) and W3C Agent utilities\n *\n * DID:WEB shapes used in Semiont:\n *\n * Knowledge base: did:web:<domain>\n * Person: did:web:<domain>:users:<email%40host>\n * Software: did:web:<domain>:agents:<provider>:<model>\n *\n * `<domain>` is the KB's committed `[site] domain` — one identity, with its\n * people and software peers named beneath it.\n *\n * `didToAgent` is the inverse: parse the DID, recognize whether the\n * subject is a person or a software peer, and return a typed Agent.\n *\n * Humans and software peers share the same identity *shape* (a DID\n * with a typed Agent on read). What differs is the path segment\n * (`:users:` vs `:agents:`) and the schema-typed fields each kind\n * carries on its Agent record.\n */\n\nimport type { components } from './types';\n\ntype Agent = components['schemas']['Agent'];\n\n/**\n * The knowledge base's own did:web identity, from its committed\n * `[site] domain` (`SemiontProject.siteDomain()`).\n *\n * Format: `did:web:<domain>` — the domain **verbatim, never encoded**. The\n * config already stores it in did:web colon-path form\n * (`the-ai-alliance.github.io:semiont-caselaw-kb`), so encoding those colons\n * would mint a string nothing else in the system produces. The launcher\n * mints the identical string in Go (`kbconfig.go` `didWeb()`), and the two\n * MUST agree byte-for-byte: the Browser joins discovered KBs to connected\n * ones on this value, and a mismatch fails silently — looking implemented\n * while never matching (.plans/KB-IDENTITY-VS-ADDRESS.md).\n *\n * A KB has no did when it declares no domain; identity is declared, never\n * defaulted or inferred from an address.\n */\nexport function kbDid(domain: string): string {\n return `did:web:${domain}`;\n}\n\n/**\n * Convert a user object to a DID:WEB identifier.\n *\n * Format: did:web:<domain>:users:<email%40domain>\n */\nexport function userToDid(user: { email: string; domain: string }): string {\n return `did:web:${user.domain}:users:${encodeURIComponent(user.email)}`;\n}\n\n/**\n * Convert a software peer's (provider, model) configuration to a DID:WEB\n * identifier. Pool-vs-individual deployment is not part of identity —\n * one DID per (provider, model) on this host.\n *\n * Format: did:web:<domain>:agents:<provider>:<model%2F-encoded>\n *\n * Model strings often contain `:` and `/` (e.g. `gemma2:27b`,\n * `library/llama3`); both must be URI-encoded so DID parsing isn't\n * ambiguous.\n */\nexport function agentToDid(agent: { domain: string; provider: string; model: string }): string {\n return `did:web:${agent.domain}:agents:${encodeURIComponent(agent.provider)}:${encodeURIComponent(agent.model)}`;\n}\n\n/**\n * Convert a user object to a typed Person Agent with a DID:WEB identifier.\n */\nexport function userToAgent(user: {\n id: string;\n domain: string;\n name: string | null;\n email: string;\n}): Agent {\n return {\n '@type': 'Person',\n '@id': userToDid(user),\n name: user.name || user.email,\n };\n}\n\n/**\n * Convert a software peer's configuration to a typed Software Agent.\n * The `name` is a stable human-friendly label, not a parseable join —\n * UI composes display from `provider`/`model` at render time.\n */\nexport function softwareToAgent(software: {\n domain: string;\n provider: string;\n model: string;\n parameters?: Record<string, unknown>;\n}): Agent {\n return {\n '@type': 'Software',\n '@id': agentToDid(software),\n name: `${software.provider} ${software.model}`,\n provider: software.provider,\n model: software.model,\n ...(software.parameters && { parameters: software.parameters }),\n };\n}\n\n/**\n * Parse a DID:WEB string into a typed Agent.\n *\n * Recognizes:\n * did:web:<host>:users:<email> → Person (name = decoded email)\n * did:web:<host>:agents:<provider>:<model> → Software (provider + model)\n *\n * Anything else falls back to a Person with the trailing segment as\n * `name`. This is the read-side inverse of `userToDid`/`agentToDid`.\n */\nexport function didToAgent(did: string | undefined | null): Agent {\n if (!did) {\n return { '@type': 'Person', '@id': 'unknown', name: 'unknown' };\n }\n const parts = did.split(':');\n\n // Find the kind segment, scanning from the right so we are not fooled\n // by `host:port` colons earlier in the string.\n const agentsIdx = parts.lastIndexOf('agents');\n const usersIdx = parts.lastIndexOf('users');\n\n if (agentsIdx >= 0 && agentsIdx === parts.length - 3) {\n const provider = decodeURIComponent(parts[agentsIdx + 1] ?? '');\n const model = decodeURIComponent(parts[agentsIdx + 2] ?? '');\n return {\n '@type': 'Software',\n '@id': did,\n name: `${provider} ${model}`,\n provider,\n model,\n };\n }\n\n if (usersIdx >= 0 && usersIdx === parts.length - 2) {\n const name = decodeURIComponent(parts[usersIdx + 1] ?? '');\n return {\n '@type': 'Person',\n '@id': did,\n name,\n };\n }\n\n // Unknown shape — preserve the DID as @id, derive a best-effort name\n // from the trailing segment. Treat as Person (the safer default for\n // unknown actors).\n const encoded = parts[parts.length - 1] || 'unknown';\n return {\n '@type': 'Person',\n '@id': did,\n name: decodeURIComponent(encoded),\n };\n}\n","/**\n * Environment validation utilities\n *\n * Pure functions - accept available environments as parameter instead of reading from filesystem\n */\n\nexport type Environment = string; // Allow any environment name\n\n/**\n * Type guard to check if a string is a valid Environment\n * @param value - The environment string to check\n * @param availableEnvironments - List of valid environment names\n */\nexport function isValidEnvironment(value: string | undefined, availableEnvironments: string[]): value is Environment {\n if (!value) return false;\n return availableEnvironments.includes(value);\n}\n\n/**\n * Parse environment string to Environment type\n * @param value - The environment string to parse\n * @param availableEnvironments - List of valid environment names\n * @returns Valid Environment type\n * @throws Error if environment is invalid or not provided\n */\nexport function parseEnvironment(value: string | undefined, availableEnvironments: string[]): Environment {\n if (!value) {\n throw new Error('Environment is required');\n }\n if (!isValidEnvironment(value, availableEnvironments)) {\n throw new Error(`Invalid environment: ${value}. Available environments: ${availableEnvironments.join(', ')}`);\n }\n return value;\n}\n\n/**\n * Validate and return environment or throw error\n * @param value - The environment string to validate\n * @param availableEnvironments - List of valid environment names\n * @throws Error if environment is invalid\n */\nexport function validateEnvironment(value: string | undefined, availableEnvironments: string[]): Environment {\n if (!value) {\n throw new Error('Environment is required');\n }\n if (!isValidEnvironment(value, availableEnvironments)) {\n throw new Error(`Invalid environment: ${value}. Available environments: ${availableEnvironments.join(', ')}`);\n }\n return value;\n}","/**\n * Configuration Error Class\n * \n * Custom error class for configuration validation and loading errors.\n * Provides structured error information with helpful suggestions.\n */\n\nexport class ConfigurationError extends Error {\n public override readonly cause?: Error;\n\n constructor(\n message: string,\n public environment?: string,\n public suggestion?: string,\n cause?: Error\n ) {\n super(message);\n this.name = 'ConfigurationError';\n this.cause = cause;\n }\n \n /**\n * Format the error nicely for CLI output\n */\n override toString(): string {\n let output = `❌ ${this.message}`;\n if (this.environment) {\n output += `\\n Environment: ${this.environment}`;\n }\n if (this.suggestion) {\n output += `\\n 💡 Suggestion: ${this.suggestion}`;\n }\n return output;\n }\n}","/**\n * Platform Types Module\n *\n * Re-exports PlatformType from schema-generated types.\n * Platforms represent WHERE services run (infrastructure targets).\n */\n\nimport { PlatformType as SchemaPlatformType } from './config.types';\n\n/**\n * Platform type literals from JSON Schema\n * These represent the infrastructure targets where services can be deployed\n */\nexport type PlatformType = SchemaPlatformType;\n\n/**\n * Type guard to check if a string is a valid platform type\n *\n * @param value - Value to check\n * @returns True if value is a valid PlatformType\n */\nexport function isValidPlatformType(value: string): value is PlatformType {\n return ['aws', 'container', 'posix', 'external'].includes(value);\n}\n\n/**\n * Get all valid platform types\n *\n * @returns Array of all platform types\n */\nexport function getAllPlatformTypes(): PlatformType[] {\n return ['aws', 'container', 'posix', 'external'];\n}","/**\n * Knowledge-graph view derivation (CONTEXT-UNIFICATION P3, Q1=A).\n *\n * A pure function over the core `KnowledgeGraph` type, so both `@semiont/make-meaning` (the matcher)\n * and `@semiont/jobs` (the generation prompt builder) can share one derivation. `buildKnowledgeGraph`\n * — which queries the graph DB — stays in make-meaning; this only transforms an already-built graph.\n *\n * Reports the graph as-is (Option A): missing-view citers are kept (the citation edge reflects a real\n * reference event); the only filter is excluding the focal annotation from siblings (an annotation\n * isn't its own sibling). Peer connections are edges out of `mainResourceId`; citations and\n * `annotation-of` edges point INTO it. The graph is a projection of the event log (the system of\n * record), read here because it is the queryable projection at gather time.\n */\nimport type { components } from './types';\n\ntype KnowledgeGraph = components['schemas']['KnowledgeGraph'];\n\nexport interface GraphViews {\n connections: { resourceId: string; resourceName: string; entityTypes: string[]; bidirectional: boolean }[];\n citedBy: { resourceId: string; resourceName: string }[];\n citedByCount: number;\n siblingEntityTypes: string[];\n}\n\nexport function deriveViews(\n graph: KnowledgeGraph,\n mainResourceId: string,\n focalAnnotationId?: string,\n): GraphViews {\n const nodeById = new Map(graph.nodes.map((n) => [n.id, n] as const));\n\n const connections: GraphViews['connections'] = [];\n const citedBy: GraphViews['citedBy'] = [];\n for (const edge of graph.edges) {\n if (edge.type === 'citation') {\n if (edge.target !== mainResourceId) continue;\n const node = nodeById.get(edge.source);\n citedBy.push({ resourceId: edge.source, resourceName: node?.label ?? edge.source });\n } else if (edge.source === mainResourceId) {\n const node = nodeById.get(edge.target);\n connections.push({\n resourceId: edge.target,\n resourceName: node?.label ?? edge.target,\n entityTypes: node?.entityTypes ?? [],\n bidirectional: edge.bidirectional ?? false,\n });\n }\n }\n\n const siblingEntityTypes = new Set<string>();\n for (const node of graph.nodes) {\n if (node.type === 'annotation' && node.id !== focalAnnotationId) {\n for (const et of node.entityTypes ?? []) siblingEntityTypes.add(et);\n }\n }\n\n return {\n connections,\n citedBy,\n citedByCount: citedBy.length,\n siblingEntityTypes: Array.from(siblingEntityTypes),\n };\n}\n","/**\n * Bounded retry with exponential backoff.\n *\n * Exists for startup-critical network calls in long-running peers (worker,\n * smelter, weaver): each authenticates against the KS the moment its\n * container starts, and the backend may not be reachable for a few seconds\n * (backend restart, container-network warm-up). Orchestration runs these\n * processes with `--rm` and no restart policy, so a process that dies on\n * the first `TypeError: fetch failed` is dead for good — the retry window\n * here is the only recovery it gets.\n */\n\nexport interface RetryPolicy {\n /** Total attempts, including the first one. */\n attempts: number;\n /** Delay before the second attempt; doubles each retry. */\n initialDelayMs: number;\n /** Ceiling for the doubled delay. */\n maxDelayMs: number;\n}\n\nexport interface RetryAttemptInfo {\n /** 1-based number of the attempt that just failed. */\n attempt: number;\n /** Total attempt budget from the policy. */\n attempts: number;\n /** How long we wait before the next attempt. */\n delayMs: number;\n error: unknown;\n}\n\n/**\n * Default policy for startup connections to the backend: 8 attempts with\n * delays 1s, 2s, 4s, then capped at 8s — ~39s of patience before giving up.\n */\nexport const STARTUP_FETCH_RETRY: RetryPolicy = {\n attempts: 8,\n initialDelayMs: 1_000,\n maxDelayMs: 8_000,\n};\n\n/**\n * True for the errors `fetch` throws when the connection itself fails —\n * undici's `TypeError: fetch failed` (ECONNREFUSED, ENOTFOUND, reset,\n * timeout — the socket error rides in `cause`). Deliberately false for\n * HTTP-level failures (a 401 means the backend is UP and rejected us;\n * retrying won't change its mind) and for programming errors.\n */\nexport function isTransientFetchError(error: unknown): boolean {\n if (!(error instanceof TypeError)) return false;\n if (error.message === 'fetch failed') return true;\n const code = (error.cause as { code?: string } | undefined)?.code;\n return typeof code === 'string' && code.length > 0;\n}\n\n/**\n * Run `fn`, retrying on errors `isRetryable` accepts, with exponential\n * backoff per `policy`. `onRetry` fires before each wait — the caller's\n * hook for logging the attempt. The final error (retryable budget\n * exhausted, or the first non-retryable one) is rethrown verbatim.\n */\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n isRetryable: (error: unknown) => boolean,\n policy: RetryPolicy,\n onRetry?: (info: RetryAttemptInfo) => void,\n): Promise<T> {\n let delayMs = policy.initialDelayMs;\n for (let attempt = 1; ; attempt++) {\n try {\n return await fn();\n } catch (error) {\n if (attempt >= policy.attempts || !isRetryable(error)) throw error;\n onRetry?.({ attempt, attempts: policy.attempts, delayMs, error });\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n delayMs = Math.min(delayMs * 2, policy.maxDelayMs);\n }\n }\n}\n","/**\n * Sharding Utilities\n *\n * Shared utilities for consistent sharding across all storage layers —\n * the event log and view storage (@semiont/event-sourcing) and the\n * anchored-text store (@semiont/content) all lay files out as\n * `{ab}/{cd}/<key>` through `getShardPath`. Hoisted here (PERSIST-ANCHORS\n * P1a) so both importers share one implementation: a second sharding\n * implementation is how two trees end up disagreeing about where\n * something lives.\n *\n * Pure string/number math — no node dependencies — so it is safe on\n * core's browser-facing root export.\n */\n\n/**\n * TEMPORARY: Simple modulo-based hash sharding\n *\n * ⚠️ TODO: Replace with proper Jump Consistent Hash implementation\n *\n * This is a TEMPORARY implementation using simple modulo. It works and provides\n * good distribution, but does NOT provide the minimal reshuffling property of\n * Jump Consistent Hash when changing bucket counts.\n *\n * The proper implementation should use Google's Jump Consistent Hash algorithm:\n * Reference: \"A Fast, Minimal Memory, Consistent Hash Algorithm\" by Lamping & Veach (2014)\n * https://arxiv.org/abs/1406.2294\n *\n * Working implementations exist in npm packages like:\n * - jumphash (https://www.npmjs.com/package/jumphash)\n * - jump-gouache (https://github.com/bhoudu/jump-gouache)\n *\n * The algorithm requires proper 64-bit integer handling with BigInt to avoid\n * precision loss in JavaScript. The previous attempt failed due to incorrect\n * BigInt arithmetic in the while loop condition.\n *\n * Until replaced, this modulo approach will cause ALL data to be reshuffled\n * if bucket count changes, rather than the optimal O(n/k) reshuffling that\n * Jump Consistent Hash provides.\n *\n * @param key - The key to hash (a resource id or content checksum)\n * @param numBuckets - Number of shards/buckets (default: 65536 for 4-hex sharding)\n * @returns Shard number (0 to numBuckets-1)\n */\nexport function jumpConsistentHash(key: string, numBuckets: number = 65536): number {\n const hash = hashToUint32(key);\n return hash % numBuckets;\n}\n\n/**\n * Hash string to 32-bit unsigned integer\n */\nfunction hashToUint32(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash = hash & 0xFFFFFFFF;\n }\n return Math.abs(hash);\n}\n\n/**\n * Convert shard number to 4-hex directory path (ab/cd)\n *\n * @param shardId - Shard number (0-65535)\n * @returns Path segments like ['ab', 'cd']\n */\nfunction shardIdToPath(shardId: number): [string, string] {\n if (shardId < 0 || shardId >= 65536) {\n throw new Error(`Invalid shard ID: ${shardId}. Must be 0-65535 for 4-hex sharding.`);\n }\n\n const shardHex = shardId.toString(16).padStart(4, '0');\n const ab = shardHex.substring(0, 2);\n const cd = shardHex.substring(2, 4);\n\n return [ab, cd];\n}\n\n/**\n * Get 4-hex shard path for a key\n *\n * @param key - The key to hash (a resource id or content checksum)\n * @param numBuckets - Number of shards (default: 65536)\n * @returns Path segments like ['ab', 'cd']\n */\nexport function getShardPath(key: string, numBuckets: number = 65536): [string, string] {\n const shardId = jumpConsistentHash(key, numBuckets);\n return shardIdToPath(shardId);\n}\n","/**\n * Browser ↔ launcher KB discovery (BROWSER-KB-DISCOVERY).\n *\n * The launcher publishes its export view at `<stateDir>/discovery/kbs.json`,\n * mounted read-only into the frontend container at `/discovery` and served\n * by the frontend image at this URL path. One TS-side name for that URL: the\n * frontend server's tests fetch this constant, so prefix/filename drift\n * between the server and consumers is a failing test — mirroring for the URL\n * what the DiscoveryDocument schema does for the payload. (The launcher's Go\n * side keeps its own constant; the plan doc is the cross-language record.)\n */\nexport const DISCOVERY_URL_PATH = '/discovery/kbs.json';\n"]}
|