// @bun
var{defineProperty:J,getOwnPropertyNames:X,getOwnPropertyDescriptor:Y}=Object,Z=Object.prototype.hasOwnProperty;function _(h){return this[h]}var S=(h)=>{var j=(Q??=new WeakMap).get(h),z;if(j)return j;if(j=J({},"__esModule",{value:!0}),h&&typeof h==="object"||typeof h==="function"){for(var A of X(h))if(!Z.call(j,A))J(j,A,{get:_.bind(h,A),enumerable:!(z=Y(h,A))||z.enumerable})}return Q.set(h,j),j},Q;var $=(h)=>h;function b(h,j){this[h]=$.bind(null,j)}var D=(h,j)=>{for(var z in j)J(h,z,{get:j[z],enumerable:!0,configurable:!0,set:b.bind(j,z)})};var R=(h,j)=>()=>(h&&(j=h(h=0)),j);var O={};D(O,{groupByToArray:()=>T,groupByMultiple:()=>U,groupBy:()=>I,getUniqueTags:()=>M,getUniqueOwners:()=>V,getUniqueDomains:()=>C,filterBy:()=>L,GroupingStrategies:()=>K});function L(h,j){return h.filter((z)=>{if(j.tags?.length){if(!j.tags.some((E)=>z.meta.tags?.includes(E)))return!1}if(j.owners?.length){if(!j.owners.some((E)=>z.meta.owners?.includes(E)))return!1}if(j.stability?.length){if(!j.stability.includes(z.meta.stability??"stable"))return!1}if(j.domain){if(K.byDomain(z)!==j.domain)return!1}if(j.keyPattern){let A=z.meta.key??z.meta.key??"",E=j.keyPattern.replace(/\*/g,".*").replace(/\?/g,".");if(!new RegExp(`^${E}$`,"i").test(A))return!1}return!0})}function I(h,j){let z=new Map;for(let A of h){let E=j(A),H=z.get(E);if(H)H.push(A);else z.set(E,[A])}return z}function T(h,j){let z=I(h,j);return Array.from(z.entries()).map(([A,E])=>({key:A,items:E}))}function U(h,j){let z=new Map;for(let A of h){let E=j(A);for(let H of E){let P=z.get(H);if(P)P.push(A);else z.set(H,[A])}}return z}function M(h){let j=new Set;for(let z of h)for(let A of z.meta.tags??[])j.add(A);return Array.from(j).sort()}function V(h){let j=new Set;for(let z of h)for(let A of z.meta.owners??[])j.add(A);return Array.from(j).sort()}function C(h){let j=new Set;for(let z of h)j.add(K.byDomain(z));return Array.from(j).sort()}var K;var W=R(()=>{K={byTag:(h)=>h.meta.tags?.[0]??"untagged",byAllTags:(h)=>h.meta.tags?.length?h.meta.tags:["untagged"],byOwner:(h)=>h.meta.owners?.[0]??"unowned",byDomain:(h)=>{return(h.meta.key??h.meta.key??"").split(".")[0]??"default"},byStability:(h)=>h.meta.stability??"stable",byUrlPath:(h)=>(j)=>{if(!j.path)return"root";return j.path.split("/").filter(Boolean).slice(0,h).join("/")||"root"}}});W();import{compareVersions as q}from"compare-versions";var B=(h)=>`${h.meta.key}.v${h.meta.version}`;class N{contractType;items=new Map;constructor(h,j){this.contractType=h;if(j)j.forEach((z)=>this.register(z))}register(h){let j=B(h);if(this.items.has(j))throw Error(`Duplicate contract \`${this.contractType}\` ${j}`);return this.items.set(j,h),this}count(){return this.items.size}list(){return[...this.items.values()]}get(h,j){if(j!=null)return this.items.get(`${h}.v${j}`);let z;for(let[A,E]of this.items.entries()){if(!A.startsWith(`${h}.v`))continue;if(!z||q(E.meta.version,z.meta.version)>0)z=E}return z}has(h,j){return!!this.get(h,j)}filter(h){return L(this.list(),h)}listByTag(h){return this.list().filter((j)=>j.meta.tags?.includes(h))}listByOwner(h){return this.list().filter((j)=>j.meta.owners?.includes(h))}groupBy(h){return I(this.list(),h)}getUniqueTags(){return M(this.list())}}class G extends N{constructor(h){super("knowledge-space",h)}getByCategory(h){return this.list().filter((j)=>j.meta.category===h)}}function u(h){return`${h.key}.v${h.version}`}var c=[{id:"docs.tech.contracts.knowledge",title:"Knowledge Layer",summary:"The knowledge layer turns unstructured inputs (uploads, email threads,",kind:"reference",visibility:"public",route:"/docs/tech/contracts/knowledge",tags:["tech","contracts","knowledge"],body:`# Knowledge Layer

The knowledge layer turns unstructured inputs (uploads, email threads,
notes) into searchable context for agents and workflows. The Pocket
Family Office vertical ships a minimal but production-ready stack that
covers ingestion, indexing, querying, and guardrails.

## Knowledge Spaces

Knowledge is organised via \`KnowledgeSpaceSpec\` definitions under
\`packages/libs/contracts-spec/src/knowledge/spaces\`:

- \`knowledge.financial-docs\` \u2013 canonical invoices, bills, and contracts.
- \`knowledge.email-threads\` \u2013 operational Gmail threads.
- \`knowledge.support-faq\` / \`knowledge.product-canon\` \u2013 reusable shared
  spaces available to any vertical.

Each space defines:

- Ownership metadata (domain, owners, stability tags).
- Retention policy (TTL/archival).
- Access policy (trust level, automation write permissions).
- Indexing configuration (embedding model, chunk size, vector DB slot).

## Sources & Bindings

- \`KnowledgeSourceConfig\` records tenant-specific connections (bucket,
  Gmail labels, sync cadence). Pocket Family Office provides sample
  configs in \`knowledge/sources.sample.ts\`.
- \`AppKnowledgeBinding\` associates spaces with workflows/agents and adds
  per-tenant constraints (rate limits, scopes).

Validation ensures that:

- All referenced spaces exist in the registry.
- At least one source is configured per binding.
- External/ephemeral spaces trigger warnings for policy-sensitive flows.

## Ingestion Pipeline

Implemented in \`@contractspec/lib.knowledge/ingestion\`:

1. **DocumentProcessor** \u2013 pluggable MIME extractors producing
   \`DocumentFragment\`s.
2. **EmbeddingService** \u2013 batches fragments through an \`EmbeddingProvider\`
   (Mistral in the reference implementation).
3. **VectorIndexer** \u2013 upserts fragments into a \`VectorStoreProvider\`
   (Qdrant in production, with in-memory implementations for tests) and
   persists canonical \`payload.text\` content alongside fragment metadata
   so retrieval and query flows can reuse indexed text directly.
4. **Adapters**
   - \`GmailIngestionAdapter\`: list threads \u2192 convert to raw documents \u2192
     index.
   - \`StorageIngestionAdapter\`: fetch object from storage provider \u2192
     index.

Background jobs (see \`@contractspec/lib.jobs\`) orchestrate ingestion via
Cloud Tasks / Pub/Sub or in-memory workers. Handlers:

- \`storage-document-handler\` \u2013 resolves storage object + indexes.
- \`gmail-sync-handler\` \u2013 syncs threads based on label/date filters.

## Query Service

\`KnowledgeQueryService\` performs retrieval-augmented generation:

1. Embed the user query using the configured provider.
2. Search the vector store for top-k matches.
3. Compose prompts combining system instructions + indexed contextual
   snippets from \`payload.text\` (falling back to legacy \`payload.content\`
   when needed).
4. Invoke the LLM provider (Mistral) and return the answer plus
   references and token usage.

The service is designed for tooling: workflows can execute it directly
or through custom operations (see \`pfo.summary.generate\` contract).

## Guardrails

- Automation can only write to spaces where \`automationWritable\` is true.
- Canonical spaces default to high trust; external/ephemeral spaces are
  flagged during validation.
- Telemetry captures query volumes per tenant + space.

## Extending

1. Define a new \`KnowledgeSpaceSpec\` with indexing/retention policies.
2. Add sources pointing to storage providers or APIs.
3. Register adapters if ingestion requires bespoke logic.
4. Reference the space in blueprints (\`AppKnowledgeBinding\`) and update
   workflows/agents accordingly.

The Pocket Family Office tests (\`tests/pocket-family-office.test.ts\`)
show how to wire the ingestion pipeline, index a document, and run an
end-to-end knowledge query using in-memory providers.
## Knowledge Spaces & Guardrails

Knowledge surfaces (\`KnowledgeSpaceSpec\`) describe curated corpora that agents and workflows can consult. Tenant bindings (\`AppKnowledgeBinding\`) declare which spaces are active, who can use them, and optional usage constraints.

### Binding recap

- \`spaceKey\` / \`spaceVersion\`: pointer to the \`KnowledgeSpaceSpec\`
- \`scope.workflows\` / \`scope.agents\`: explicit allow-lists for consumers
- \`constraints.maxTokensPerQuery\` & \`constraints.maxQueriesPerMinute\`: throttling knobs for LLM-backed search
- \`required\`: mark the binding as blocking (defaults to \`true\`)

At runtime, \`ResolvedAppConfig.knowledge\` contains \`ResolvedKnowledge\` entries with the bound space, active sources, and the binding metadata above.

### KnowledgeAccessGuard

\`KnowledgeAccessGuard\` (\`@contractspec/lib.knowledge/access/guard\`) centralises the access checks that must run before any workflow/agent reads or mutates a knowledge space.

\`\`\`ts
import { KnowledgeAccessGuard } from '@contractspec/lib.knowledge/access/guard';

const guard = new KnowledgeAccessGuard({
  disallowWriteCategories: ['external', 'ephemeral'], // default
  requireWorkflowBinding: true,
  requireAgentBinding: false,
});

const result = guard.checkAccess(resolvedKnowledge, {
  tenantId,
  appId,
  workflowName: 'order-processing',
  operation: 'read', // or 'write' / 'search'
}, resolvedAppConfig);

if (!result.allowed) {
  throw new Error(result.reason);
}
\`\`\`

Key behaviours:

- **Binding**: rejects access when the space is not present in the resolved tenant config.
- **Category guardrails**: blocks writes to \`external\` and \`ephemeral\` spaces by default; allows reads but emits warnings for \`ephemeral\`.
- **Workflow/agent scoping**: when \`requireWorkflowBinding\` or \`requireAgentBinding\` is enabled, only explicitly authorised consumers may access the space.

Use the guard inside workflow operations or agent resolvers to guarantee multi-tenant isolation and honour data governance rules.

## Agent memory tools and ephemeral spaces

Ephemeral spaces (\`category: 'ephemeral'\`) are the canonical home for agent memory storage (scratchpads, session context, drafts). Agent memory tools (Anthropic \`memory_20250818\`, custom operation-backed) can use ephemeral spaces as storage when configured with \`memoryTools.spaceKey\`.

### Enabling agent memory writes

By default, \`KnowledgeAccessGuard\` blocks writes to ephemeral spaces (\`disallowWriteCategories: ['external', 'ephemeral']\`). To allow agent memory tools to write:

1. Configure \`disallowWriteCategories: ['external']\` (allow ephemeral writes).
2. Ensure \`AppKnowledgeBinding.scope.agents\` includes the agent key when using knowledge-backed storage.
3. Set \`requireAgentBinding: true\` so only explicitly bound agents can write.

See \`@contractspec/lib.ai-agent\` memory tools and \`AgentMemoryStore\` for implementation details.
`}];export{c as tech_contracts_knowledge_DocBlocks,u as makeKnowledgeSpaceKey,G as KnowledgeSpaceRegistry};
