{"slug":"architecture/v2-capability-layer","title":"Capability Layer and OODA Runtime — IntegrateWise Continuity Bridge v2.0","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/v2-capability-layer.mdx","bytes":107744,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n> **Status: SUPERSEDED DEEP-DIVE.** Retained for implementation genealogy only.\n> The frozen OODA grammar, Capability boundary and execution path are defined by\n> [`ARCHITECTURE_LOCK.md`](./ARCHITECTURE_LOCK.md),\n> [`FOUR_BUTTONS.md`](./FOUR_BUTTONS.md) and\n> [`IMPLEMENTATION_CONTRACT_v1.1.md`](./IMPLEMENTATION_CONTRACT_v1.1.md).\n\n**Domain:** Capability Layer and OODA Runtime — Capability Registry, Platform SDK, Platform Contracts, Context Assembly, Capability Runtime, ADK Runtime, MCP Runtime, Execution Routing, OODA Phase Mapping, Agent vs Pipeline Boundaries  \n**Status:** STAGE 1/2 DEEP-DIVE — PRODUCTION SPECIFICATION  \n**Version:** 2.0.0-DRAFT  \n**Date:** 2026-07-02  \n**Supersedes:** v1.0.1-FINAL §6 (Tier 3), §7 (Layers 9–11), §12 (AI/Twin/Reasoning)\n\n---\n\n## 0. Domain Position in the 6-Layer Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│  Layer 1: Identity            — JWT, RBAC, Tenant Resolution, SSO           │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  Layer 2: Ingress             — Gateway, Webhook-Ingress, Inbound MCP Pool  │\n├─────────────────────────────────────────────────────────────────────────────┤\n│▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶▶│\n│  Layer 3: CAPABILITY          — THIS DOCUMENT — The OODA Execution Fabric   │\n│                               Capability Registry · Context Assembly        │\n│                               ADK Runtime · MCP Runtime · Execution Routing │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  Layer 4: Continuity          — The Moat · Spine · Memory · Knowledge       │\n│                               Twin-orchestrator (AMBIENT) · Triage          │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  Layer 5: Governance          — Confidence Gates · HITL · Audit · Policy    │\n├─────────────────────────────────────────────────────────────────────────────┤\n│  Layer 6: Provider Fabric     — Adapter Modules · Nango · MCP · Native REST │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n**Invariant:** The Capability Layer is the **only** layer that can initiate outbound execution. It does not store context (that is Continuity), it does not govern (that is Governance), and it does not touch providers directly (that is the Provider Fabric via adapter modules). The Capability Layer **orchestrates** — it routes, assembles, reasons, and dispatches.\n\n---\n\n## 1. Core Doctrine for This Domain\n\n> **The Capability Layer turns intent into execution. It does not own data. It does not own memory. It owns the contract between \"what the user wants\" and \"what the system can do.\"**\n\nThe Capability Layer exposes five canonical primitives to all consumers:\n\n| Primitive        | Contract                                             | Runtime                                               |\n| ---------------- | ---------------------------------------------------- | ----------------------------------------------------- |\n| **Identity**     | `whoami` — JWT claims, tenant, org, role             | `gateway` → `tenants`                                 |\n| **Discovery**    | `GET /api/v1/discovery` — what exists, what can I do | `gateway` → `agent-registry` + `intelligence`         |\n| **Projections**  | L1–L4 capability tiers — persona-specific views      | `l2`, `store`, `intelligence`                         |\n| **Capabilities** | Named business actions with typed schemas            | `capability-registry` → `hermes` → `act` / `workflow` |\n| **Events**       | Signal, Proposal, Approval, Outcome, Stream          | `hermes` + `mcp-connector` + `telemetry`              |\n\n**The Twin is AMBIENT.** It is not a separate service that consumers call. It is the persistent reasoning substrate that lives _inside_ the Capability Runtime, accessible via the `twin-orchestrator` Durable Object, surfaced through capabilities like `twin/propose` and `insights`. Consumers never interact with `twin-orchestrator` directly — they invoke capabilities that _use_ the Twin.\n\n---\n\n## 2. Capability Registry\n\n### 2.1 Purpose\n\nThe Capability Registry is the **single source of truth** for every named action the platform can perform. It is a living catalog — not a static file. Capabilities are registered at deploy time, discovered at runtime, and validated on every invocation.\n\n### 2.2 Registry Schema (D1 + KV Cache)\n\n```typescript\n// packages/spine-schema/src/schema/capability-registry.ts\n\n\n  id: text(\"id\").primaryKey(), // capability URI: \"salesforce.opportunity.update\"\n  tenantId: text(\"tenant_id\").notNull(), // NULLABLE for platform-level capabilities\n  namespace: text(\"namespace\").notNull(), // \"salesforce\", \"twin\", \"platform\"\n  name: text(\"name\").notNull(), // \"opportunity.update\"\n  displayName: text(\"display_name\"), // \"Update Opportunity\"\n  description: text(\"description\"),\n  version: text(\"version\").notNull().default(\"1.0.0\"),\n\n  // OODA phase classification\n  oodaPhase: text(\"ooda_phase\", {\n    enum: [\"observe\", \"orient\", \"decide\", \"act\", \"cross-phase\"],\n  }).notNull(),\n\n  // Execution routing\n  runtime: text(\"runtime\", {\n    enum: [\"agent\", \"pipeline\", \"workflow\", \"mcp\", \"direct\"],\n  }).notNull(),\n\n  // Routing target\n  serviceBinding: text(\"service_binding\").notNull(),\n  handler: text(\"handler\").notNull(), // \"execute\", \"propose\", \"sync\", \"invoke\"\n\n  // Schema references\n  inputSchema: text(\"input_schema\"), // JSON Schema URI\n  outputSchema: text(\"output_schema\"), // JSON Schema URI\n\n  // Governance\n  requiresApproval: integer(\"requires_approval\", { mode: \"boolean\" }).default(false),\n  minConfidence: real(\"min_confidence\").default(0.7),\n  autoApproveThreshold: real(\"auto_approve_threshold\").default(0.85),\n\n  // Authorization\n  requiredRoles: text(\"required_roles\"), // JSON array of RBAC role IDs\n  requiredScopes: text(\"required_scopes\"), // JSON array: [\"read\", \"write\", \"admin\"]\n\n  // Metadata\n  isActive: integer(\"is_active\", { mode: \"boolean\" }).default(true),\n  isDeprecated: integer(\"is_deprecated\", { mode: \"boolean\" }).default(false),\n  deprecationNote: text(\"deprecation_note\"),\n  createdAt: integer(\"created_at\", { mode: \"timestamp\" }).$defaultFn(() => new Date()),\n  updatedAt: integer(\"updated_at\", { mode: \"timestamp\" }).$defaultFn(() => new Date()),\n});\n\n// Platform SDK Contract table — shared across all SDK clients\n  id: text(\"id\").primaryKey(), // contract URI\n  capabilityId: text(\"capability_id\").references(() => capabilityRegistry.id),\n  contractType: text(\"contract_type\", {\n    enum: [\"request\", \"response\", \"event\", \"error\", \"schema\"],\n  }).notNull(),\n  schema: blob(\"schema\", { mode: \"json\" }).notNull(), // JSON Schema\n  version: text(\"version\").notNull(),\n  isBreaking: integer(\"is_breaking\", { mode: \"boolean\" }).default(false),\n  migrationPath: text(\"migration_path\"), // URI to migration guide\n});\n```\n\n### 2.3 Capability URI Format\n\n```\ncapability := <namespace> \".\" <name>\nnamespace  := \"platform\" | \"twin\" | <provider> | \"ecosystem\"\nprovider   := \"salesforce\" | \"hubspot\" | \"slack\" | \"github\" | \"stripe\" | ...\nname       := <resource> \".\" <action>\n```\n\n**Examples:**\n\n- `salesforce.opportunity.update` — Provider capability, Act phase\n- `twin.propose` — Twin reasoning capability, Decide phase\n- `platform.discovery` — Platform capability, Observe phase\n- `ecosystem.broadcast` — Cross-tenant knowledge sharing, Cross-phase\n\n### 2.4 Registry Operations\n\n```typescript\n// services/agent-registry/src/registry.ts\n\ninterface CapabilityRegistryAPI {\n  /**\n   * Register a new capability. Called by service deploy hooks.\n   * Writes to D1, invalidates KV cache.\n   */\n  register(capability: CapabilityRegistration): Promise<RegistrationResult>;\n\n  /**\n   * Resolve a capability URI to its runtime configuration.\n   * Hot path — reads from KV cache first, D1 fallback.\n   */\n  resolve(capabilityUri: string, tenantId: string): Promise<ResolvedCapability>;\n\n  /**\n   * List capabilities filtered by tenant, role, OODA phase, runtime.\n   * Powers Discovery endpoint.\n   */\n  list(filters: CapabilityFilter): Promise<CapabilityList>;\n\n  /**\n   * Validate a capability invocation against its schema and permissions.\n   */\n  validate(\n    capabilityUri: string,\n    tenantId: string,\n    callerRole: string,\n    payload: unknown\n  ): Promise<ValidationResult>;\n\n  /**\n   * Deprecate a capability. Marks as deprecated, schedules removal.\n   */\n  deprecate(capabilityUri: string, note: string): Promise<void>;\n}\n\ninterface CapabilityRegistration {\n  id: string; // capability URI\n  namespace: string;\n  name: string;\n  oodaPhase: OodaPhase;\n  runtime: RuntimeType;\n  serviceBinding: string; // e.g., \"ACT\", \"WORKFLOW\", \"IW_AGENT_RUNTIME\"\n  handler: string;\n  inputSchema: JsonSchema;\n  outputSchema: JsonSchema;\n  requiredRoles?: string[];\n  requiredScopes?: string[];\n  requiresApproval?: boolean;\n  minConfidence?: number;\n  autoApproveThreshold?: number;\n}\n\ninterface ResolvedCapability {\n  capability: typeof capabilityRegistry.$inferSelect;\n  contract: PlatformContract;\n  route: ServiceRoute; // Which binding + handler to call\n  cacheHit: boolean;\n}\n```\n\n### 2.5 Registry Caching Strategy\n\n| Tier                     | TTL        | Source                                           | Invalidation                           |\n| ------------------------ | ---------- | ------------------------------------------------ | -------------------------------------- |\n| **KV Cache**             | 5 min      | `agent-registry` writes to KV on registration    | Service deploy, manual registry update |\n| **D1**                   | Persistent | Source of truth                                  | Never directly by runtime              |\n| **Service Binding Memo** | 30 sec     | `gateway` memoizes binding resolution per tenant | TTL expiry                             |\n\n---\n\n## 3. Platform SDK and Platform Contracts\n\n### 3.1 Platform SDK — Consumer Contract\n\nThe Platform SDK (`packages/sdk/`) is the **only** consumer-facing code artifact. It provides typed wrappers around every capability. Consumers import `@integratewise/sdk` — they never import internal service topology.\n\n```typescript\n// packages/sdk/src/capabilities.ts\n\n\n/**\n * The Platform SDK exposes every capability as a typed method.\n * Each method validates input against the capability's JSON Schema,\n * routes to the correct service binding, and deserializes the response.\n */\nexport class PlatformSDK {\n  constructor(private client: CapabilityClient) {}\n\n  // ── Observe Phase Capabilities ──\n\n  async discover(tenantId: string): Promise<DiscoveryResponse> {\n    return this.client.invoke(\"platform.discovery\", tenantId, {});\n  }\n\n  async querySignals(tenantId: string, filter: SignalFilter): Promise<SignalStream> {\n    return this.client.invoke(\"platform.signals.query\", tenantId, filter);\n  }\n\n  // ── Orient Phase Capabilities ──\n\n  async getEntity360(tenantId: string, entityType: string, entityId: string): Promise<Entity360> {\n    return this.client.invoke(\"platform.entity360.get\", tenantId, {\n      entityType,\n      entityId,\n    });\n  }\n\n  async assembleContext(\n    tenantId: string,\n    request: ContextAssemblyRequest\n  ): Promise<AssembledContext> {\n    return this.client.invoke(\"intelligence.context.assemble\", tenantId, request);\n  }\n\n  // ── Decide Phase Capabilities ──\n\n  async twinPropose(tenantId: string, userId: string, prompt: string): Promise<Proposal> {\n    return this.client.invoke(\"twin.propose\", tenantId, {\n      userId,\n      prompt,\n      // Twin is ambient — this capability routes to twin-orchestrator DO\n    });\n  }\n\n  async twinAnalyze(tenantId: string, entityType: string, entityId: string): Promise<Analysis> {\n    return this.client.invoke(\"twin.analyze\", tenantId, {\n      entityType,\n      entityId,\n    });\n  }\n\n  // ── Act Phase Capabilities ──\n\n  async executeCapability(\n    tenantId: string,\n    capabilityUri: string,\n    payload: unknown\n  ): Promise<ExecutionResult> {\n    return this.client.invoke(capabilityUri, tenantId, payload);\n  }\n\n  async runWorkflow(\n    tenantId: string,\n    workflowType: string,\n    input: unknown\n  ): Promise<WorkflowHandle> {\n    return this.client.invoke(\"workflow.start\", tenantId, {\n      type: workflowType,\n      input,\n    });\n  }\n\n  // ── Ecosystem Capabilities ──\n\n  async broadcastKnowledge(\n    tenantId: string,\n    knowledge: KnowledgePacket\n  ): Promise<EcosystemReceipt> {\n    return this.client.invoke(\"ecosystem.broadcast\", tenantId, knowledge);\n  }\n}\n```\n\n### 3.2 Platform Contract Types\n\n```typescript\n// packages/sdk/src/contracts.ts\n\n/**\n * Every capability invocation follows this envelope.\n * This is the wire format between Gateway and all internal services.\n */\nexport interface CapabilityInvocation {\n  /** Capability URI being invoked */\n  capability: string;\n\n  /** Tenant scope — extracted from JWT claim, never from client payload */\n  tenantId: string;\n\n  /** User scope — extracted from JWT sub claim */\n  userId: string;\n\n  /** Caller role — from JWT rbac claim */\n  role: string;\n\n  /** Correlation ID for distributed tracing */\n  correlationId: string;\n\n  /** JWT scope array */\n  scopes: string[];\n\n  /** The actual payload — validated against capability.inputSchema */\n  payload: unknown;\n\n  /** Context assembly hints — passed to intelligence service */\n  contextHints?: ContextHint[];\n\n  /** Requested OODA phase — used for routing and telemetry */\n  oodaPhase: OodaPhase;\n}\n\nexport interface CapabilityResponse<T = unknown> {\n  success: boolean;\n  data?: T;\n  error?: CapabilityError;\n\n  /** Confidence score — populated by Decide-phase capabilities */\n  confidence?: number;\n\n  /** Governance state — for capabilities requiring approval */\n  governance?: GovernanceState;\n\n  /** Telemetry metadata */\n  meta: ResponseMeta;\n}\n\nexport interface CapabilityError {\n  code: string; // \"CAPABILITY_NOT_FOUND\" | \"VALIDATION_FAILED\" | \"GOVERNANCE_DENIED\" | ...\n  message: string;\n  details?: Record<string, unknown>;\n  retryable: boolean;\n}\n\nexport interface ResponseMeta {\n  correlationId: string;\n  durationMs: number;\n  serviceBinding: string;\n  cacheHit: boolean;\n  oodaPhase: OodaPhase;\n}\n```\n\n---\n\n## 4. Context Assembly\n\n### 4.1 Purpose\n\nContext Assembly is the **Orient phase engine**. It gathers Entity360, Memory, Knowledge, and Evidence into a structured context window for reasoning and execution. It runs in the `intelligence` service (Layer 7 in the 0–16 stack).\n\n### 4.2 Assembly Pipeline\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                          CONTEXT ASSEMBLY PIPELINE                          │\n│                         (services/intelligence/src/)                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  INPUT: CapabilityInvocation + ContextHints                                 │\n│       │                                                                     │\n│       ▼                                                                     │\n│  ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐     │\n│  │  Stage 1    │──▶│  Stage 2    │──▶│  Stage 3    │──▶│  Stage 4    │     │\n│  │  RESOLVE    │   │   FETCH     │   │  ASSEMBLE   │   │  OPTIMIZE   │     │\n│  │             │   │             │   │             │   │             │     │\n│  │ • Entity    │   │ • Spine     │   │ • Merge     │   │ • Truncate  │     │\n│  │   resolution│   │   entities  │   │   sources   │   │   to window │     │\n│  │ • SSOC bind │   │ • Memory    │   │ • Rank by   │   │ • Prioritize│     │\n│  │ • Type infer│   │ • Knowledge │   │   relevance │   │ • Deduplicate│    │\n│  └─────────────┘   │ • Evidence  │   │ • Inject    │   │ • Compress  │     │\n│                    └─────────────┘   │   metadata  │   └─────────────┘     │\n│                                      └─────────────┘                       │\n│                                                                             │\n│  OUTPUT: AssembledContext (Entity360 + Memory + Knowledge + Tools)         │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 4.3 TypeScript Interfaces\n\n```typescript\n// packages/sdk/src/context.ts\n\n/**\n * The output of Context Assembly — fed into the Twin for reasoning\n * or into the Capability Runtime for execution.\n */\nexport interface AssembledContext {\n  /** The entity at the center of this context window */\n  entity360: Entity360;\n\n  /** Relevant memory entries — active tier, ranked by recency + relevance */\n  memory: MemoryEntry[];\n\n  /** Knowledge base hits — RAG results from Vectorize + AI Search */\n  knowledge: KnowledgeHit[];\n\n  /** Available tools/capabilities for this tenant + role */\n  tools: ToolCatalog;\n\n  /** Evidence — audit trail, past decisions, lineage */\n  evidence: Evidence[];\n\n  /** Relationship graph — connected entities within 2 hops */\n  relationships: Relationship[];\n\n  /** Assembled prompt — ready for LLM consumption */\n  prompt: StructuredPrompt;\n\n  /** Metadata about the assembly process */\n  assemblyMeta: AssemblyMeta;\n}\n\nexport interface Entity360 {\n  id: string; // SSOC stable UUID\n  type: string; // \"account\", \"contact\", \"opportunity\", ...\n  tenantId: string;\n\n  /** Canonical properties from Spine */\n  properties: Record<string, unknown>;\n\n  /** Computed traits from Normalizer */\n  traits: EntityTrait[];\n\n  /** Temporal context — when this entity was created, updated, last seen */\n  timeline: EntityTimeline;\n\n  /** Projection data — L1/L2 lens overlays */\n  projections: ProjectionData;\n\n  /** Source-of-truth provenance */\n  provenance: Provenance[];\n}\n\nexport interface MemoryEntry {\n  id: string;\n  scope: \"Personal\" | \"Work\" | \"Organization\" | \"AI\";\n  tier: \"active\" | \"staging\" | \"archived\";\n  content: string;\n  confidence: number; // TriageBot score\n  source: string; // Which service created this memory\n  createdAt: Date;\n  accessedAt: Date;\n  reinforcementCount: number; // How many times this memory was reinforced\n}\n\nexport interface KnowledgeHit {\n  id: string;\n  source: string; // Document name, URL, or KB entry\n  content: string;\n  embeddingScore: number; // Vectorize cosine similarity\n  semanticScore: number; // AI Search relevance\n  chunkIndex: number; // Which chunk of the document\n}\n\nexport interface ToolCatalog {\n  /** Capabilities available to this tenant + role + context */\n  capabilities: ResolvedCapability[];\n\n  /** Tool schemas for LLM function calling */\n  schemas: Record<string, JsonSchema>;\n\n  /** Tool descriptions for prompt injection */\n  descriptions: ToolDescription[];\n}\n\nexport interface StructuredPrompt {\n  /** System prompt — platform identity, constraints, safety rules */\n  system: string;\n\n  /** Context window — the assembled Entity360 + Memory + Knowledge */\n  context: string;\n\n  /** Available tools — formatted for the specific LLM provider */\n  tools: string;\n\n  /** The user's actual request */\n  user: string;\n\n  /** Total token count estimate */\n  estimatedTokens: number;\n\n  /** Model that will consume this prompt */\n  targetModel: string;\n}\n\nexport interface AssemblyMeta {\n  correlationId: string;\n  stagesCompleted: string[]; // [\"resolve\", \"fetch\", \"assemble\", \"optimize\"]\n  durationMs: number;\n  sourcesQueried: number;\n  memoryEntriesScanned: number;\n  knowledgeChunksScanned: number;\n  tokensBeforeOptimization: number;\n  tokensAfterOptimization: number;\n}\n```\n\n### 4.4 Context Assembly Service Interface\n\n```typescript\n// services/intelligence/src/context-assembly.ts\n\nexport interface ContextAssemblyEngine {\n  /**\n   * Assemble a full context window for reasoning or execution.\n   * This is the hot path for every Twin proposal and every Act execution.\n   */\n  assemble(request: ContextAssemblyRequest): Promise<AssembledContext>;\n\n  /**\n   * Lightweight entity resolution — SSOC lookup only.\n   * Used by Observe-phase handlers that don't need full context.\n   */\n  resolveEntity(tenantId: string, entityType: string, entityId: string): Promise<Entity360 | null>;\n\n  /**\n   * Memory-only retrieval — used by continuity service for decay decisions.\n   */\n  queryMemory(tenantId: string, query: MemoryQuery): Promise<MemoryEntry[]>;\n\n  /**\n   * Tool catalog assembly — used by MCP /tools endpoint.\n   */\n  assembleToolCatalog(tenantId: string, role: string, scopes: string[]): Promise<ToolCatalog>;\n}\n\nexport interface ContextAssemblyRequest {\n  tenantId: string;\n  userId: string;\n  correlationId: string;\n\n  /** The primary entity being operated on */\n  primaryEntity?: {\n    type: string;\n    id: string;\n  };\n\n  /** The user's natural language request (for Twin reasoning) */\n  naturalLanguage?: string;\n\n  /** Explicit context hints from the caller */\n  hints?: ContextHint[];\n\n  /** Maximum tokens for the assembled context */\n  maxTokens?: number;\n\n  /** Which OODA phase is requesting context — affects depth */\n  forPhase: OodaPhase;\n}\n\nexport interface ContextHint {\n  type: \"include_memory\" | \"include_knowledge\" | \"focus_entity\" | \"time_range\" | \"lens\";\n  value: string | Record<string, unknown>;\n  priority: number; // 0.0–1.0, higher = more important\n}\n```\n\n---\n\n## 5. OODA Phase Mapping\n\n### 5.1 The OODA Loop in the Capability Layer\n\nOODA runs **across** the Capability Layer (Layer 3) and the Continuity Layer (Layer 4). The Capability Layer owns the execution fabric; the Continuity Layer owns the state substrate. The Twin is the ambient reasoning engine that bridges both.\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                        OODA LOOP — PLATFORM MAPPING                         │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   OBSERVE ─────────────────────────────────────────────────────────────►    │\n│   │                                                                         │\n│   │  • webhook-ingress    (webhooks, events, signals)                       │\n│   │  • connector-sync     (poll-based sync)                                 │\n│   │  • folder-watcher     (filesystem changes)                              │\n│   │  • mcp-connector      (inbound MCP tool calls)                          │\n│   │  • platform.signals.* (signal query capabilities)                       │\n│   │                                                                         │\n│   ▼                                                                         │\n│   ORIENT ───────────────────────────────────────────────────────────────►   │\n│   │                                                                         │\n│   │  • intelligence       (Context Assembly — Entity360, Memory, Knowledge) │\n│   │  • knowledge          (RAG, semantic search)                            │\n│   │  • continuity         (memory retrieval, SSOC resolution)               │\n│   │  • normalizer         (8-stage canonicalization)                        │\n│   │  • platform.entity360.get                                              │\n│   │  • intelligence.context.assemble                                       │\n│   │                                                                         │\n│   ▼                                                                         │\n│   DECIDE ───────────────────────────────────────────────────────────────►   │\n│   │                                                                         │\n│   │  • twin-orchestrator  (persistent per-user DO — reasoning engine)       │\n│   │  • think              (LLM orchestration — OpenRouter abstraction)      │\n│   │  • govern             (confidence scoring, proposal evaluation)         │\n│   │  • twin.propose       (capability: generate proposal)                   │\n│   │  • twin.analyze       (capability: analyze entity)                      │\n│   │  • twin.predict       (capability: generate forecast)                   │\n│   │                                                                         │\n│   ▼                                                                         │\n│   ACT ──────────────────────────────────────────────────────────────────►   │\n│   │                                                                         │\n│   │  • hermes             (message queue + execution routing)               │\n│   │  • workflow           (durable orchestration — sagas, retries)          │\n│   │  • act                (outbound execution + adapter modules)            │\n│   │  • iw-agent-runtime   (MCP-compliant agent execution)                   │\n│   │  • mcp-connector      (outbound MCP calls — inside act adapters)        │\n│   │  • platform.execute.* (generic execution capability)                    │\n│   │                                                                         │\n│   └────────────────────────────────────────────────────────────────────►    │\n│        (memory compounds) ──▶ continuity (memory consolidation)             │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 5.2 Phase-to-Service Matrix\n\n| OODA Phase  | Primary Services                                                                 | Capability Runtime                       | Data Layer                             | Speed Target                        |\n| ----------- | -------------------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------- | ----------------------------------- |\n| **Observe** | `webhook-ingress`, `connector-sync`, `folder-watcher`, `mcp-connector` (inbound) | Event ingestion only                     | Spine read (Entity360 for routing)     | ms–min                              |\n| **Orient**  | `intelligence`, `knowledge`, `continuity`, `normalizer`                          | Context Assembly engine                  | D1 + Vectorize + KV + AI Search        | <2s normalizer p99, <10ms cache hit |\n| **Decide**  | `twin-orchestrator`, `think`, `govern`                                           | Proposal generation + confidence scoring | OpenRouter API, KV model config        | 1–2s simple, 5–10s complex          |\n| **Act**     | `hermes`, `workflow`, `act`, `iw-agent-runtime`                                  | Execution routing + adapter dispatch     | Durable Objects, Queues, external APIs | 500ms–2s (external API)             |\n\n### 5.3 Phase-to-Queue Mapping\n\n```typescript\n// infra/queues/definitions.ts\n\n/**\n * Queue topology for OODA execution.\n * Each phase has its own queue to prevent head-of-line blocking.\n */\n  // Observe → Orient handoff\n  OBSERVE_QUEUE: \"iw-observe-queue\",\n\n  // Orient → Decide handoff (context assembly complete, ready for reasoning)\n  ORIENT_QUEUE: \"iw-orient-queue\",\n\n  // Decide → Act handoff (proposal approved or auto-approved)\n  ACT_QUEUE: \"iw-act-queue\",\n\n  // Act → Continuity handoff (execution result, writeback pending)\n  PIPELINE_QUEUE: \"iw-pipeline-queue\",\n\n  // Governance review queue (0.70–0.85 proposals awaiting HITL)\n  GOVERNANCE_QUEUE: \"iw-governance-queue\",\n\n  // Cross-cutting: telemetry, audit, memory triage\n  TELEMETRY_QUEUE: \"iw-telemetry-queue\",\n  MEMORY_TRIAGE_QUEUE: \"iw-memory-triage-queue\",\n} as const;\n\n/**\n * Dead letter queues — every primary queue has a corresponding DLQ.\n */\n  OBSERVE_DLQ: \"iw-observe-dlq\",\n  ACT_DLQ: \"iw-act-dlq\",\n  PIPELINE_DLQ: \"iw-pipeline-dlq\",\n} as const;\n```\n\n---\n\n## 6. Capability Runtime\n\n### 6.1 Architecture\n\nThe Capability Runtime is the **execution fabric** of Layer 3. It receives capability invocations from the Gateway, resolves them through the Capability Registry, assembles context, routes to the appropriate handler, and manages the lifecycle of every execution.\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                         CAPABILITY RUNTIME                                  │\n│                    (Layer 3 — Execution Orchestration)                      │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ┌──────────────┐     ┌──────────────────┐     ┌──────────────────┐        │\n│  │   Gateway    │────▶│ CapabilityRouter │────▶│  RegistryCache   │        │\n│  │  (Layer 2)   │     │   (hermes DO)    │     │    (KV + D1)     │        │\n│  └──────────────┘     └──────────────────┘     └──────────────────┘        │\n│                              │                                              │\n│              ┌───────────────┼───────────────┐                              │\n│              ▼               ▼               ▼                              │\n│        ┌──────────┐    ┌──────────┐    ┌──────────┐                        │\n│        │  Direct  │    │  Agent   │    │ Workflow │                        │\n│        │ Handler  │    │ Runtime  │    │ Engine   │                        │\n│        │ (act)    │    │(iw-agent │    │(workflow│                        │\n│        │          │    │ runtime) │    │ DO)      │                        │\n│        └──────────┘    └──────────┘    └──────────┘                        │\n│              │               │               │                              │\n│              └───────────────┼───────────────┘                              │\n│                              ▼                                              │\n│                    ┌──────────────────┐                                    │\n│                    │  Adapter Layer   │  ◄── Provider Fabric (Layer 6)    │\n│                    │  (act adapters)  │                                    │\n│                    └──────────────────┘                                    │\n│                              │                                              │\n│                              ▼                                              │\n│                    ┌──────────────────┐                                    │\n│                    │  PIPELINE_QUEUE  │  ──▶ Spine Writeback (Layer 4)    │\n│                    └──────────────────┘                                    │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 6.2 CapabilityRouter — Hermes Durable Object\n\n```typescript\n// services/hermes/src/router.ts\n\n/**\n * Hermes is the central message queue + execution router.\n * It is implemented as a Durable Object to maintain stateful routing tables,\n * in-flight execution tracking, and backpressure management.\n */\nexport class CapabilityRouter {\n  private registry: CapabilityRegistryAPI;\n  private contextAssembly: ContextAssemblyEngine;\n  private governance: GovernanceGate;\n  private telemetry: TelemetryCollector;\n\n  constructor(state: DurableObjectState, env: Env) {\n    this.registry = new CachedRegistry(env);\n    this.contextAssembly = new ContextAssemblyClient(env.INTELLIGENCE);\n    this.governance = new GovernanceGate(env.GOVERN);\n    this.telemetry = new TelemetryCollector(env.TELEMETRY);\n  }\n\n  /**\n   * Main entry point for all capability invocations.\n   * Routes through: Resolve → Validate → Assemble Context → Execute → Writeback\n   */\n  async route(invocation: CapabilityInvocation): Promise<CapabilityResponse> {\n    const start = Date.now();\n\n    try {\n      // 1. RESOLVE — capability URI → runtime config\n      const resolved = await this.registry.resolve(invocation.capability, invocation.tenantId);\n\n      if (!resolved) {\n        return this.error(\n          \"CAPABILITY_NOT_FOUND\",\n          `No capability registered for ${invocation.capability}`\n        );\n      }\n\n      // 2. VALIDATE — schema + permissions\n      const validation = await this.registry.validate(\n        invocation.capability,\n        invocation.tenantId,\n        invocation.role,\n        invocation.payload\n      );\n\n      if (!validation.valid) {\n        return this.error(\"VALIDATION_FAILED\", validation.errors.join(\"; \"));\n      }\n\n      // 3. GOVERNANCE PRE-CHECK — block before expensive operations\n      if (resolved.capability.requiresApproval) {\n        const preCheck = await this.governance.preCheck(invocation);\n        if (preCheck === \"DENY\") {\n          return this.error(\"GOVERNANCE_DENIED\", \"This capability requires explicit approval\");\n        }\n      }\n\n      // 4. CONTEXT ASSEMBLY (for Orient+ phases)\n      let context: AssembledContext | undefined;\n      if ([\"orient\", \"decide\", \"act\", \"cross-phase\"].includes(resolved.capability.oodaPhase)) {\n        context = await this.contextAssembly.assemble({\n          tenantId: invocation.tenantId,\n          userId: invocation.userId,\n          correlationId: invocation.correlationId,\n          forPhase: resolved.capability.oodaPhase,\n          hints: invocation.contextHints,\n        });\n      }\n\n      // 5. EXECUTE — route to the appropriate runtime\n      const result = await this.execute(resolved, invocation, context);\n\n      // 6. POST-EXECUTION GOVERNANCE (for Decide phase)\n      if (resolved.capability.oodaPhase === \"decide\" && result.confidence !== undefined) {\n        const governanceResult = await this.governance.evaluate({\n          capability: invocation.capability,\n          tenantId: invocation.tenantId,\n          userId: invocation.userId,\n          confidence: result.confidence,\n          proposal: result.data,\n        });\n\n        result.governance = governanceResult;\n\n        // Auto-approve or queue for review\n        if (governanceResult.action === \"queue\") {\n          await this.enqueueGovernanceReview(invocation, result);\n        }\n      }\n\n      // 7. TELEMETRY\n      await this.telemetry.record({\n        correlationId: invocation.correlationId,\n        capability: invocation.capability,\n        tenantId: invocation.tenantId,\n        durationMs: Date.now() - start,\n        success: true,\n        oodaPhase: resolved.capability.oodaPhase,\n        runtime: resolved.capability.runtime,\n      });\n\n      return {\n        success: true,\n        data: result.data,\n        confidence: result.confidence,\n        governance: result.governance,\n        meta: {\n          correlationId: invocation.correlationId,\n          durationMs: Date.now() - start,\n          serviceBinding: resolved.capability.serviceBinding,\n          cacheHit: resolved.cacheHit,\n          oodaPhase: resolved.capability.oodaPhase,\n        },\n      };\n    } catch (err) {\n      await this.telemetry.record({\n        correlationId: invocation.correlationId,\n        capability: invocation.capability,\n        tenantId: invocation.tenantId,\n        durationMs: Date.now() - start,\n        success: false,\n        error: err instanceof Error ? err.message : String(err),\n      });\n\n      return this.error(\"EXECUTION_ERROR\", err instanceof Error ? err.message : String(err));\n    }\n  }\n\n  /**\n   * Execute the capability through the appropriate runtime.\n   */\n  private async execute(\n    resolved: ResolvedCapability,\n    invocation: CapabilityInvocation,\n    context?: AssembledContext\n  ): Promise<ExecutionResult> {\n    const enrichedPayload = {\n      ...invocation.payload,\n      _context: context,\n      _tenantId: invocation.tenantId,\n      _userId: invocation.userId,\n      _correlationId: invocation.correlationId,\n    };\n\n    switch (resolved.capability.runtime) {\n      case \"direct\":\n        // Direct execution via service binding (synchronous, <100ms)\n        return this.executeDirect(resolved, enrichedPayload);\n\n      case \"agent\":\n        // Agent runtime — MCP-compliant AI agent execution\n        return this.executeAgent(resolved, enrichedPayload);\n\n      case \"pipeline\":\n        // Pipeline execution — enqueues to PIPELINE_QUEUE\n        return this.executePipeline(resolved, enrichedPayload);\n\n      case \"workflow\":\n        // Durable workflow — saga pattern, retries, pause/resume\n        return this.executeWorkflow(resolved, enrichedPayload);\n\n      case \"mcp\":\n        // MCP outbound execution — via act service MCP adapter\n        return this.executeMCP(resolved, enrichedPayload);\n\n      default:\n        throw new Error(`Unknown runtime: ${resolved.capability.runtime}`);\n    }\n  }\n\n  private async executeDirect(\n    resolved: ResolvedCapability,\n    payload: unknown\n  ): Promise<ExecutionResult> {\n    const binding = resolved.capability.serviceBinding;\n    // Service binding call — synchronous RPC\n    const service = this.env[binding] as ServiceBinding;\n    return service\n      .fetch(\n        new Request(\"http://internal/execute\", {\n          method: \"POST\",\n          body: JSON.stringify({\n            handler: resolved.capability.handler,\n            payload,\n          }),\n        })\n      )\n      .then((r) => r.json());\n  }\n\n  private async executeAgent(\n    resolved: ResolvedCapability,\n    payload: unknown\n  ): Promise<ExecutionResult> {\n    // Route to iw-agent-runtime for MCP-compliant agent execution\n    const agentRuntime = this.env.IW_AGENT_RUNTIME as ServiceBinding;\n    return agentRuntime\n      .fetch(\n        new Request(\"http://internal/agent/execute\", {\n          method: \"POST\",\n          body: JSON.stringify({\n            capability: resolved.capability.id,\n            payload,\n          }),\n        })\n      )\n      .then((r) => r.json());\n  }\n\n  private async executeWorkflow(\n    resolved: ResolvedCapability,\n    payload: unknown\n  ): Promise<ExecutionResult> {\n    // Start a durable workflow — returns a handle, not a result\n    const workflow = this.env.WORKFLOW as ServiceBinding;\n    const handle = await workflow\n      .fetch(\n        new Request(\"http://internal/workflow/start\", {\n          method: \"POST\",\n          body: JSON.stringify({\n            type: resolved.capability.handler,\n            input: payload,\n          }),\n        })\n      )\n      .then((r) => r.json());\n\n    return {\n      data: { workflowId: handle.id, status: \"started\" },\n    };\n  }\n\n  private async executeMCP(\n    resolved: ResolvedCapability,\n    payload: unknown\n  ): Promise<ExecutionResult> {\n    // Route to act service — MCP outbound adapter handles provider specifics\n    const act = this.env.ACT as ServiceBinding;\n    return act\n      .fetch(\n        new Request(\"http://internal/mcp/execute\", {\n          method: \"POST\",\n          body: JSON.stringify({\n            capability: resolved.capability.id,\n            payload,\n          }),\n        })\n      )\n      .then((r) => r.json());\n  }\n\n  private error(code: string, message: string): CapabilityResponse {\n    return {\n      success: false,\n      error: { code, message, retryable: code !== \"VALIDATION_FAILED\" },\n      meta: {\n        correlationId: \"\", // populated by caller\n        durationMs: 0,\n        serviceBinding: \"hermes\",\n        cacheHit: false,\n        oodaPhase: \"observe\",\n      },\n    };\n  }\n}\n```\n\n### 6.3 Execution Result Contract\n\n```typescript\n// packages/sdk/src/execution.ts\n\nexport interface ExecutionResult {\n  /** The primary output of the execution */\n  data?: unknown;\n\n  /** Confidence score — set by Decide-phase capabilities */\n  confidence?: number;\n\n  /** Governance state — populated for capabilities requiring approval */\n  governance?: GovernanceState;\n\n  /** For workflow executions — the workflow handle */\n  workflowHandle?: WorkflowHandle;\n\n  /** For streaming capabilities — SSE stream reference */\n  streamRef?: string;\n\n  /** Side effects — what was written, what changed */\n  sideEffects?: SideEffect[];\n\n  /** Whether the result should be written back to Spine */\n  requiresWriteback: boolean;\n\n  /** Memory entries to persist */\n  memoryToCreate?: MemoryEntryDraft[];\n}\n\nexport interface GovernanceState {\n  status: \"auto_approved\" | \"pending_review\" | \"denied\" | \"escalated\";\n  confidence: number;\n  threshold: number;\n  reviewer?: string;\n  reviewedAt?: Date;\n  auditRef: string; // Reference to governance_audit_log entry\n}\n\nexport interface SideEffect {\n  type: \"spine_write\" | \"memory_create\" | \"event_emit\" | \"notification\";\n  target: string;\n  payload: unknown;\n}\n\nexport interface WorkflowHandle {\n  id: string;\n  status: \"pending\" | \"running\" | \"paused\" | \"completed\" | \"failed\";\n  checkpointUrl: string;\n}\n\nexport interface MemoryEntryDraft {\n  scope: \"Personal\" | \"Work\" | \"Organization\" | \"AI\";\n  content: string;\n  confidence: number;\n  source: string;\n}\n```\n\n---\n\n## 7. ADK Runtime (Ambient Twin Development Kit)\n\n### 7.1 Architecture\n\nThe ADK Runtime is the **persistent reasoning substrate** that powers the Twin. It is not a separate service that consumers call — it is the engine behind `twin.propose`, `twin.analyze`, and `twin.predict` capabilities. The ADK Runtime lives inside the `twin-orchestrator` Durable Object and the `think` service.\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                         ADK RUNTIME ARCHITECTURE                            │\n│                     (Ambient — Not Directly Callable)                       │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   Consumer ──▶ capability \"twin.propose\" ──▶ Hermes Router                  │\n│                                                  │                          │\n│                                                  ▼                          │\n│   ┌──────────────────────────────────────────────────────────────┐         │\n│   │              TWIN-ORCHESTRATOR (Durable Object)                │         │\n│   │                                                              │         │\n│   │  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐       │         │\n│   │  │   Session   │───▶│   Memory    │───▶│   Reason    │       │         │\n│   │  │   State     │    │   Graph     │    │   Engine    │       │         │\n│   │  │             │    │             │    │             │       │         │\n│   │  │ • User pref │    │ • Personal  │    │ • think svc │       │         │\n│   │  │ • Active    │    │ • Work      │    │ • OpenRouter│       │         │\n│   │  │   context   │    │ • Org       │    │ • Model sel │       │         │\n│   │  │ • Last N    │    │ • AI        │    │ • Chain-of- │       │         │\n│   │  │   turns     │    │             │    │   thought   │       │         │\n│   │  └─────────────┘    └─────────────┘    └─────────────┘       │         │\n│   │         │                   │                   │             │         │\n│   │         └───────────────────┴───────────────────┘             │         │\n│   │                             │                                 │         │\n│   │                             ▼                                 │         │\n│   │                    ┌─────────────────┐                        │         │\n│   │                    │  OODA Engine    │                        │         │\n│   │                    │  (inside DO)    │                        │         │\n│   │                    │                 │                        │         │\n│   │                    │ Observe ──▶ Orient ──▶ Decide ──▶ Act    │         │\n│   │                    │   │             │          │         │   │         │\n│   │                    │   ▼             ▼          ▼         ▼   │         │\n│   │                    │ Spine      Context    Proposal  Execute │         │\n│   │                    │ read       Assembly     + conf   route  │         │\n│   │                    └─────────────────┘                        │         │\n│   │                              │                                │         │\n│   │                              ▼                                │         │\n│   │                    ┌─────────────────┐                        │         │\n│   │                    │  Proposal Output │  ──▶ Govern ──▶ Act   │         │\n│   │                    │  + Confidence    │                        │         │\n│   │                    └─────────────────┘                        │         │\n│   │                                                              │         │\n│   └──────────────────────────────────────────────────────────────┘         │\n│                                                                             │\n│   KEY INVARIANT: The Twin is AMBIENT. Consumers call capabilities.          │\n│   The Twin is the reasoning engine INSIDE those capabilities.               │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 7.2 ADK Runtime Interfaces\n\n```typescript\n// packages/twin-types/src/adk.ts\n\n/**\n * The ADK Runtime is the persistent per-user reasoning engine.\n * Each user gets one Durable Object instance: idFromName(tenantId + userId)\n */\nexport interface ADKRuntime {\n  /**\n   * Generate a proposal based on the current context.\n   * This is the core Decide-phase capability.\n   */\n  propose(request: ProposeRequest): Promise<Proposal>;\n\n  /**\n   * Analyze an entity and return structured insights.\n   */\n  analyze(request: AnalyzeRequest): Promise<Analysis>;\n\n  /**\n   * Generate a forecast or prediction.\n   */\n  predict(request: PredictRequest): Promise<Prediction>;\n\n  /**\n   * Ingest a new observation into the Twin's session state.\n   * Called by Observe-phase handlers to keep the Twin current.\n   */\n  observe(event: TwinObservation): Promise<void>;\n\n  /**\n   * Get the current OODA state of this Twin session.\n   */\n  getState(): Promise<TwinState>;\n\n  /**\n   * Reinforce a memory — mark it as important, reset decay clock.\n   */\n  reinforce(memoryId: string): Promise<void>;\n}\n\nexport interface ProposeRequest {\n  tenantId: string;\n  userId: string;\n  prompt: string;\n\n  /** Optional: focus on a specific entity */\n  targetEntity?: {\n    type: string;\n    id: string;\n  };\n\n  /** Optional: constrain to specific capability namespaces */\n  capabilityNamespaces?: string[];\n\n  /** Maximum number of proposals to generate */\n  maxProposals?: number;\n\n  /** Whether to include evidence citations in proposals */\n  includeEvidence?: boolean;\n}\n\nexport interface Proposal {\n  id: string;\n  correlationId: string;\n\n  /** The proposed action */\n  action: {\n    capability: string; // e.g., \"salesforce.opportunity.update\"\n    payload: unknown;\n    description: string; // Human-readable description\n  };\n\n  /** Reasoning trace */\n  reasoning: string;\n\n  /** Evidence supporting this proposal */\n  evidence: Evidence[];\n\n  /** Confidence score — 0.0 to 1.0 */\n  confidence: number;\n\n  /** Estimated impact */\n  impact: {\n    type: \"revenue\" | \"risk\" | \"efficiency\" | \"relationship\";\n    score: number; // -1.0 to 1.0\n    description: string;\n  };\n\n  /** Alternative actions considered */\n  alternatives: Alternative[];\n\n  /** Governance requirements */\n  governance: {\n    requiresApproval: boolean;\n    autoApproveThreshold: number;\n    minConfidence: number;\n  };\n\n  /** Model used to generate this proposal */\n  model: string;\n\n  createdAt: Date;\n}\n\nexport interface TwinState {\n  sessionId: string;\n  userId: string;\n  tenantId: string;\n\n  /** Current OODA phase */\n  currentPhase: OodaPhase;\n\n  /** Turn count in this session */\n  turnCount: number;\n\n  /** Active context window */\n  activeContext: AssembledContext;\n\n  /** Pending proposals awaiting governance */\n  pendingProposals: Proposal[];\n\n  /** Last interaction timestamp */\n  lastActiveAt: Date;\n\n  /** Session health */\n  health: {\n    contextSize: number; // tokens\n    memoryEntries: number;\n    modelLatencyAvg: number; // ms\n    errorRate: number; // 0.0–1.0\n  };\n}\n\nexport interface TwinObservation {\n  type: \"signal\" | \"event\" | \"user_action\" | \"execution_result\";\n  source: string; // Which service produced this observation\n  payload: unknown;\n  timestamp: Date;\n  entityRefs?: string[]; // SSOC UUIDs referenced\n}\n```\n\n### 7.3 Think Service — LLM Orchestration\n\n```typescript\n// services/think/src/engine.ts\n\n/**\n * The Think service is the LLM abstraction layer.\n * It routes to OpenRouter by default, but is swappable to any OpenAI-compatible endpoint.\n * It handles model selection, prompt formatting, retry logic, and circuit breaking.\n */\nexport interface ThinkEngine {\n  /**\n   * Generate a completion from the configured model provider.\n   */\n  complete(request: CompletionRequest): Promise<CompletionResponse>;\n\n  /**\n   * Generate a structured output (JSON mode).\n   */\n  structured<T>(request: StructuredRequest<T>): Promise<T>;\n\n  /**\n   * Stream a completion (SSE).\n   */\n  stream(request: CompletionRequest): ReadableStream;\n\n  /**\n   * Select the optimal model for a given capability and context.\n   */\n  selectModel(capability: string, contextComplexity: number): string;\n}\n\nexport interface CompletionRequest {\n  prompt: string | StructuredPrompt;\n  model?: string; // Override default model selection\n  maxTokens?: number;\n  temperature?: number;\n  tools?: ToolDescription[]; // For function calling\n\n  /** Which capability is requesting this completion — used for model selection */\n  forCapability?: string;\n}\n\nexport interface CompletionResponse {\n  content: string;\n  model: string;\n  usage: {\n    promptTokens: number;\n    completionTokens: number;\n    totalTokens: number;\n  };\n  finishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\";\n  toolCalls?: ToolCall[];\n}\n```\n\n---\n\n## 8. MCP Runtime\n\n### 8.1 Bidirectional MCP Architecture\n\nMCP is **first-class** in the Capability Layer. There are two distinct MCP runtimes:\n\n1. **Inbound MCP Runtime** (`mcp-connector` service) — AI assistants connect TO us\n2. **Outbound MCP Runtime** (inside `act` service adapters) — We connect TO provider MCP servers\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                      MCP RUNTIME — BIDIRECTIONAL POOL                       │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ┌─────────────────────────────────┐    ┌─────────────────────────────────┐ │\n│  │     INBOUND MCP POOL            │    │     OUTBOUND MCP POOL           │ │\n│  │     (North Plane — Layer 2)     │    │     (South Plane — Layer 6)     │ │\n│  │                                 │    │                                 │ │\n│  │  Claude ──▶ mcp.integratewise   │    │   act service                   │ │\n│  │  ChatGPT    .ai/v1/mcp          │    │   ├── MCPOutboundAdapter        │ │\n│  │  Cursor     │                   │    │   │   ├── Salesforce MCP        │ │\n│  │  Perplexity │  ┌───────────┐    │    │   │   ├── Slack MCP             │ │\n│  │             └──▶│ MCP       │    │    │   │   ├── GitHub MCP            │ │\n│  │                 │ Connector │    │    │   │   └── Custom MCP            │ │\n│  │                 │ Service   │    │    │   │                             │ │\n│  │                 │           │    │    │   └── Entity360 injection       │ │\n│  │                 │ • /tools  │    │    │       before every call         │ │\n│  │                 │ • /invoke │    │    │                                 │ │\n│  │                 │ • /health │    │    │   Credential wall per tenant    │ │\n│  │                 └───────────┘    │    │   (CF Secrets / KV)             │ │\n│  │                      │          │    │                                 │ │\n│  │                      ▼          │    │                                 │ │\n│  │              ┌──────────────┐   │    │   ┌──────────────┐              │ │\n│  │              │  Tool Catalog │   │    │   │  Result      │              │ │\n│  │              │  Assembly     │   │    │   │  Normalizer  │              │ │\n│  │              │               │   │    │   │              │              │ │\n│  │              │ • Filter by   │   │    │   │ • Map to     │              │ │\n│  │              │   tenant/role │   │    │   │   Spine      │              │ │\n│  │              │ • Schema      │   │    │   │   schema     │              │ │\n│  │              │   validation  │   │    │   │ • Enqueue    │              │ │\n│  │              └──────────────┘   │    │   │   to Pipeline│              │ │\n│  │                                 │    │   └──────────────┘              │ │\n│  └─────────────────────────────────┘    └─────────────────────────────────┘ │\n│                                                                             │\n│  SECURITY: Both pools enforce tenant isolation, JWT validation, and         │\n│  read-only default. Write requires governance approval.                     │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 8.2 Inbound MCP Runtime\n\n```typescript\n// services/mcp-connector/src/runtime.ts\n\n/**\n * Inbound MCP Runtime — AI assistants connect to us via SSE.\n * Multi-tenant: one Worker, many sessions, each session bound to a tenant.\n */\nexport class InboundMCPRuntime {\n  /**\n   * Handle SSE transport negotiation.\n   */\n  async createSession(request: Request): Promise<MCPSession> {\n    const jwt = this.extractJWT(request);\n    const claims = await this.verifyJWT(jwt);\n    const tenantId = claims.tenant_id;\n    const userId = claims.sub;\n\n    // Security: fail-loud on cross-tenant session reuse\n    const sessionId = crypto.randomUUID();\n    const sessionKey = `mcp:session:${tenantId}:${sessionId}`;\n\n    await this.env.KV.put(\n      sessionKey,\n      JSON.stringify({\n        tenantId,\n        userId,\n        role: claims.rbac_role,\n        scopes: claims.scopes,\n        createdAt: Date.now(),\n      }),\n      { expirationTtl: 3600 }\n    );\n\n    return { id: sessionId, tenantId, userId };\n  }\n\n  /**\n   * Assemble the tool catalog for this tenant + role.\n   * Read-only tools are always included. Write tools require scope:write.\n   */\n  async getToolCatalog(session: MCPSession): Promise<Tool[]> {\n    const cacheKey = `mcp:tools:${session.tenantId}:${session.role}`;\n    const cached = await this.env.KV.get(cacheKey);\n\n    if (cached) {\n      return JSON.parse(cached);\n    }\n\n    // Fetch from Capability Registry\n    const capabilities = await this.registry.list({\n      tenantId: session.tenantId,\n      role: session.role,\n      isActive: true,\n    });\n\n    // Map capabilities to MCP Tool format\n    const tools = capabilities.items.map((cap) => ({\n      name: cap.id,\n      description: cap.description || cap.displayName,\n      inputSchema: cap.inputSchema,\n      // Read-only default: only include write tools if scope includes \"write\"\n      readOnly: !cap.requiredScopes?.includes(\"write\"),\n    }));\n\n    // Cache for 5 minutes\n    await this.env.KV.put(cacheKey, JSON.stringify(tools), { expirationTtl: 300 });\n\n    return tools;\n  }\n\n  /**\n   * Invoke a capability via MCP.\n   * Routes through Hermes (CapabilityRouter) for full OODA execution.\n   */\n  async invokeTool(session: MCPSession, toolName: string, arguments: unknown): Promise<ToolResult> {\n    // Resolve the capability\n    const resolved = await this.registry.resolve(toolName, session.tenantId);\n\n    if (!resolved) {\n      return { error: `Tool ${toolName} not found for this tenant` };\n    }\n\n    // Read-only gate\n    if (\n      resolved.capability.requiredScopes?.includes(\"write\") &&\n      !session.scopes.includes(\"write\")\n    ) {\n      return { error: \"Write scope required for this tool\" };\n    }\n\n    // Build CapabilityInvocation and route through Hermes\n    const invocation: CapabilityInvocation = {\n      capability: toolName,\n      tenantId: session.tenantId,\n      userId: session.userId,\n      role: session.role,\n      correlationId: crypto.randomUUID(),\n      scopes: session.scopes,\n      payload: arguments,\n      oodaPhase: resolved.capability.oodaPhase,\n    };\n\n    const result = await this.hermes.route(invocation);\n\n    // Audit\n    await this.audit.log({\n      via: \"mcp\",\n      tenantId: session.tenantId,\n      userId: session.userId,\n      capability: toolName,\n      success: result.success,\n      correlationId: invocation.correlationId,\n    });\n\n    return {\n      content: result.success ? JSON.stringify(result.data) : JSON.stringify(result.error),\n      isError: !result.success,\n    };\n  }\n}\n```\n\n### 8.3 Outbound MCP Adapter (Inside `act`)\n\n```typescript\n// services/act/src/adapters/mcp-outbound.ts\n\n/**\n * MCP Outbound Adapter — connects to provider MCP servers.\n * Part of the adapter pattern inside the act service.\n */\nexport class MCPOutboundAdapter implements OutboundAdapter {\n  constructor(\n    private provider: string,\n    private serverUrl: string,\n    private credentialStore: CredentialStore\n  ) {}\n\n  async execute(\n    resource: string,\n    operation: string,\n    payload: unknown,\n    credentials: Credentials\n  ): Promise<ExecutionResult> {\n    // 1. Fetch Entity360 context for injection\n    const entityContext = payload[\"_context\"] as AssembledContext | undefined;\n    const entity360 = entityContext?.entity360;\n\n    // 2. Build MCP tool call\n    const toolCall = {\n      name: `${this.provider}.${resource}.${operation}`,\n      arguments: this.enrichPayload(payload, entity360),\n    };\n\n    // 3. Call provider MCP server\n    const response = await fetch(this.serverUrl, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${credentials.accessToken}`,\n        \"Content-Type\": \"application/json\",\n        \"X-Tenant-Id\": credentials.tenantId,\n      },\n      body: JSON.stringify({\n        jsonrpc: \"2.0\",\n        method: \"tools/call\",\n        params: toolCall,\n        id: crypto.randomUUID(),\n      }),\n    });\n\n    if (!response.ok) {\n      throw new Error(`MCP outbound call failed: ${response.status} ${await response.text()}`);\n    }\n\n    const result = await response.json();\n\n    // 4. Normalize result to Spine schema\n    const normalizedResult = await this.normalizeResult(result, resource, operation);\n\n    // 5. Enqueue to Pipeline for writeback\n    await this.enqueueWriteback({\n      tenantId: credentials.tenantId,\n      capability: `${this.provider}.${resource}.${operation}`,\n      result: normalizedResult,\n    });\n\n    return {\n      data: normalizedResult,\n      requiresWriteback: true,\n    };\n  }\n\n  private enrichPayload(payload: unknown, entity360?: Entity360): unknown {\n    if (!entity360) return payload;\n\n    // Inject relevant Entity360 properties into the payload\n    // Provider-specific enrichment rules live in config\n    return {\n      ...payload,\n      _context: {\n        entityId: entity360.id,\n        entityType: entity360.type,\n        entityProperties: entity360.properties,\n      },\n    };\n  }\n\n  private async normalizeResult(\n    result: unknown,\n    resource: string,\n    operation: string\n  ): Promise<unknown> {\n    // Normalize provider-specific response to Spine canonical schema\n    // Delegates to normalizer service via queue for complex normalization\n    return result;\n  }\n}\n```\n\n---\n\n## 9. Execution Routing\n\n### 9.1 Routing Decision Tree\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                        EXECUTION ROUTING LOGIC                              │\n│                         (Inside Hermes Router)                              │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  INPUT: CapabilityInvocation                                                │\n│       │                                                                     │\n│       ▼                                                                     │\n│  ┌─────────────────┐                                                        │\n│  │ Resolve from    │                                                        │\n│  │ Capability      │                                                        │\n│  │ Registry        │                                                        │\n│  └────────┬────────┘                                                        │\n│           │                                                                 │\n│           ▼                                                                 │\n│  ┌─────────────────┐                                                        │\n│  │ OODA Phase?     │                                                        │\n│  └────────┬────────┘                                                        │\n│           │                                                                 │\n│     ┌─────┴─────┬─────────┬─────────┐                                       │\n│     ▼           ▼         ▼         ▼                                       │\n│  observe     orient    decide      act                                      │\n│     │           │         │         │                                       │\n│     ▼           ▼         ▼         ▼                                       │\n│  Direct      Context    Twin      Hermes                                    │\n│  Handler     Assembly   + Think   Queue                                     │\n│  (sync)      (async)    (async)   (async)                                   │\n│     │           │         │         │                                       │\n│     ▼           ▼         ▼         ▼                                       │\n│  Return     Return     Return     Enqueue                                  │\n│  <100ms     <2s        1-10s      to ACT_QUEUE                             │\n│                                                                             │\n│  ┌────────────────────────────────────────────────────────────────────┐    │\n│  │ Runtime Selection (after phase routing):                           │    │\n│  │                                                                    │    │\n│  │ runtime === \"direct\"    ──▶ Service Binding RPC (sync)             │    │\n│  │ runtime === \"agent\"     ──▶ iw-agent-runtime (MCP execution)       │    │\n│  │ runtime === \"pipeline\"  ──▶ Enqueue to PIPELINE_QUEUE              │    │\n│  │ runtime === \"workflow\"  ──▶ Start Workflow DO (saga)               │    │\n│  │ runtime === \"mcp\"       ──▶ act service → MCPOutboundAdapter       │    │\n│  └────────────────────────────────────────────────────────────────────┘    │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 9.2 Routing Interface\n\n```typescript\n// services/hermes/src/routing.ts\n\n/**\n * The RoutingTable maps capabilities to their execution runtime.\n * It is populated from the Capability Registry at deploy time and\n * refreshed every 30 seconds from KV cache.\n */\nexport interface RoutingTable {\n  /**\n   * Get the route for a capability URI.\n   */\n  getRoute(capabilityUri: string): RouteEntry | undefined;\n\n  /**\n   * Refresh the routing table from the Capability Registry.\n   */\n  refresh(): Promise<void>;\n\n  /**\n   * Register a dynamic route (for runtime-discovered capabilities).\n   */\n  registerDynamicRoute(entry: RouteEntry): void;\n}\n\nexport interface RouteEntry {\n  capabilityUri: string;\n\n  /** Primary target */\n  target: {\n    serviceBinding: string; // e.g., \"ACT\", \"WORKFLOW\", \"IW_AGENT_RUNTIME\"\n    handler: string; // e.g., \"execute\", \"start\", \"agent/execute\"\n  };\n\n  /** Fallback target if primary fails */\n  fallback?: {\n    serviceBinding: string;\n    handler: string;\n  };\n\n  /** Circuit breaker config */\n  circuitBreaker: {\n    failureThreshold: number;\n    recoveryTimeout: number; // ms\n    halfOpenMaxCalls: number;\n  };\n\n  /** Retry config */\n  retry: {\n    maxRetries: number;\n    backoffType: \"fixed\" | \"exponential\";\n    backoffMs: number;\n  };\n\n  /** Timeout config */\n  timeout: {\n    requestTimeoutMs: number;\n    deadlineMs: number;\n  };\n}\n```\n\n---\n\n## 10. Agent vs Pipeline Boundaries\n\n### 10.1 The Fundamental Distinction\n\n| Dimension      | **Agent** (iw-agent-runtime)                           | **Pipeline** (pipeline service)           |\n| -------------- | ------------------------------------------------------ | ----------------------------------------- |\n| **Purpose**    | Execute AI-driven, reasoning-intensive capabilities    | Write canonical data to the Spine         |\n| **Runtime**    | MCP-compliant, LLM-orchestrated                        | Deterministic, schema-validated           |\n| **Input**      | Natural language + Entity360 + Tools                   | Normalized canonical records              |\n| **Output**     | Proposals, analysis, predictions, tool calls           | Spine entities, relationships, audit logs |\n| **State**      | Stateful (Durable Object per user)                     | Stateless (single Worker, all tenants)    |\n| **Governance** | Always through confidence gate                         | Always through schema validation          |\n| **Speed**      | 1–10s (LLM latency)                                    | <2s p99 (database writes)                 |\n| **Queue**      | `ORIENT_QUEUE` → `ACT_QUEUE`                           | `PIPELINE_QUEUE`                          |\n| **Moat**       | The Twin is ambient — consumers don't call it directly | Pipeline is the **ONLY** Spine writer     |\n\n### 10.2 When to Use Agent vs Pipeline\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                    AGENT VS PIPELINE DECISION MATRIX                        │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  Consumer Request                                                           │\n│       │                                                                     │\n│       ▼                                                                     │\n│  ┌─────────────────────────┐                                               │\n│  │ Requires reasoning,     │                                               │\n│  │ LLM, or Twin?           │                                               │\n│  └───────────┬─────────────┘                                               │\n│              │                                                             │\n│         ┌────┴────┐                                                        │\n│         ▼         ▼                                                        │\n│       YES        NO                                                        │\n│         │         │                                                        │\n│         ▼         ▼                                                        │\n│   ┌─────────┐  ┌─────────────┐                                             │\n│   │  AGENT  │  │  PIPELINE   │                                             │\n│   │  PATH   │  │  PATH       │                                             │\n│   │         │  │             │                                             │\n│   │ Route   │  │ Route to    │                                             │\n│   │ to      │  │ pipeline    │                                             │\n│   │ twin-   │  │ service     │                                             │\n│   │ orchestr│  │             │                                             │\n│   │ ator or │  │ Validate    │                                             │\n│   │ iw-agen-│  │ schema      │                                             │\n│   │ t-runtim│  │ Write to    │                                             │\n│   │ e       │  │ Spine       │                                             │\n│   │         │  │ Emit audit  │                                             │\n│   │ Generate│  │             │                                             │\n│   │ proposal│  │             │                                             │\n│   │ + conf  │  │             │                                             │\n│   │         │  │             │                                             │\n│   │ Govern  │  │             │                                             │\n│   │ eval    │  │             │                                             │\n│   │         │  │             │                                             │\n│   │ Execute │  │             │                                             │\n│   │ via act │  │             │                                             │\n│   └─────────┘  └─────────────┘                                             │\n│                                                                             │\n│  KEY RULE: Pipeline NEVER calls LLM. Agent NEVER writes to Spine directly.  │\n│  The only path from Agent to Spine is: Agent ──▶ Act ──▶ PIPELINE_QUEUE     │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 10.3 Boundary Enforcement\n\n```typescript\n// packages/lib/src/boundaries.ts\n\n/**\n * Boundary enforcement — compile-time and runtime checks to ensure\n * Agents and Pipelines do not violate their separation of concerns.\n */\n\n// Agent boundary: Agents MUST NOT write to D1 directly\n  if (serviceName === \"iw-agent-runtime\" || serviceName === \"twin-orchestrator\") {\n    // These services have NO D1 binding in their wrangler.toml\n    // Attempting to import db-gate.ts will fail at build time\n  }\n}\n\n// Pipeline boundary: Pipeline MUST be the only Spine writer\n  if (operation.startsWith(\"INSERT\") || operation.startsWith(\"UPDATE\")) {\n    if (serviceName !== \"pipeline\") {\n      throw new Error(\n        `SPINE_WRITE_VIOLATION: Only 'pipeline' may write to Spine. ` +\n          `Attempted by '${serviceName}'. ` +\n          `Use PIPELINE_QUEUE instead.`\n      );\n    }\n  }\n}\n\n// Runtime check: every D1 query must pass through pipeline service\nexport async function spineWrite(payload: SpineWritePayload): Promise<void> {\n  // This function ONLY exists in the pipeline service\n  // All other services call this via service binding or queue\n  throw new Error(\"spineWrite is only available in pipeline service\");\n}\n```\n\n---\n\n## 11. Security Boundaries\n\n### 11.1 Capability Layer Security Model\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                    CAPABILITY LAYER SECURITY BOUNDARIES                     │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  BOUNDARY 1: Identity Gate (Layer 1)                                │   │\n│  │  ─────────────────────────────────                                  │   │\n│  │  • JWT validation on every capability invocation                    │   │\n│  │  • tenant_id extracted from JWT claim ONLY                          │   │\n│  │  • role + scopes from JWT rbac claim                                │   │\n│  │  • x-correlation-id injected for tracing                            │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n│                                    │                                        │\n│                                    ▼                                        │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  BOUNDARY 2: Capability Registry Gate                               │   │\n│  │  ────────────────────────────────────                               │   │\n│  │  • Capability URI must exist in registry                            │   │\n│  │  • Tenant must have access to this capability (plan limits)         │   │\n│  │  • Caller role must match requiredRoles                             │   │\n│  │  • Caller scopes must include requiredScopes                        │   │\n│  │  • Deprecated capabilities return 410 Gone                          │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n│                                    │                                        │\n│                                    ▼                                        │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  BOUNDARY 3: Context Assembly Gate                                  │   │\n│  │  ─────────────────────────────────                                  │   │\n│  │  • Entity360 scoped to tenant_id (WHERE tenant_id = ?)              │   │\n│  │  • Memory scoped to tenant_id + user_id                             │   │\n│  │  • Knowledge scoped to tenant_id                                    │   │\n│  │  • Cross-tenant context assembly → 403 fail-loud                    │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n│                                    │                                        │\n│                                    ▼                                        │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  BOUNDARY 4: Governance Gate (Layer 5)                              │   │\n│  │  ─────────────────────────────────                                  │   │\n│  │  • Confidence < 0.70 → discard                                      │   │\n│  │  • 0.70 ≤ confidence < 0.85 → queue for HITL review                 │   │\n│  │  • confidence ≥ 0.85 → auto-approve                                 │   │\n│  │  • Every decision logged to governance_audit_log                    │   │\n│  │  • Audit write failure → halt operation                             │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n│                                    │                                        │\n│                                    ▼                                        │\n│  ┌─────────────────────────────────────────────────────────────────────┐   │\n│  │  BOUNDARY 5: Execution Gate (Layer 6)                               │   │\n│  │  ─────────────────────────────────                                  │   │\n│  │  • Adapter modules inside act service ONLY                          │   │\n│  │  • Credential wall: per-tenant credentials from CF Secrets/KV       │   │\n│  │  • Entity360 injection before every outbound call                   │   │\n│  │  • No shared tokens across tenants                                  │   │\n│  │  • Every outbound call logged to outbound_mcp_calls                 │   │\n│  └─────────────────────────────────────────────────────────────────────┘   │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n### 11.2 Security Checklist for Capability Layer\n\n| #   | Check                                         | Implementation                                              |\n| --- | --------------------------------------------- | ----------------------------------------------------------- |\n| 1   | Every capability invocation carries valid JWT | `gateway` validates, passes claims via service binding      |\n| 2   | `tenant_id` never from client payload         | Extracted from JWT `tenant_id` claim only                   |\n| 3   | Cross-tenant capability resolution → 403      | Registry query includes `WHERE tenant_id = ?`               |\n| 4   | Read-only default for MCP                     | `scope: read` in JWT; write requires `scope: write`         |\n| 5   | Tool catalog filtered by tenant               | `agent-registry.list()` enforces `tenant_id` filter         |\n| 6   | Every invocation audited                      | `spine_audit_log` with `via: capability`                    |\n| 7   | Capability schema validated before execution  | `registry.validate()` runs JSON Schema validation           |\n| 8   | Agent cannot write to Spine directly          | Build-time restriction: no D1 binding in `iw-agent-runtime` |\n| 9   | Pipeline cannot call LLM                      | Build-time restriction: no OpenRouter import in `pipeline`  |\n| 10  | Dead-letter queues for every queue            | `OBSERVE_DLQ`, `ACT_DLQ`, `PIPELINE_DLQ`                    |\n\n---\n\n## 12. Integration Points with Adjacent Layers\n\n### 12.1 Northbound: Ingress Layer (Layer 2)\n\n| Integration                  | Contract                                                 | Direction            |\n| ---------------------------- | -------------------------------------------------------- | -------------------- |\n| `gateway` → `hermes`         | `CapabilityInvocation` via service binding               | Ingress → Capability |\n| `mcp-connector` → `hermes`   | MCP `tools/call` → `CapabilityInvocation`                | Ingress → Capability |\n| `webhook-ingress` → `hermes` | Webhook payload → `CapabilityInvocation` (observe phase) | Ingress → Capability |\n\n### 12.2 Southbound: Continuity Layer (Layer 4)\n\n| Integration               | Contract                                      | Direction               |\n| ------------------------- | --------------------------------------------- | ----------------------- |\n| `hermes` → `intelligence` | `ContextAssemblyRequest` → `AssembledContext` | Capability → Continuity |\n| `hermes` → `continuity`   | Memory retrieval for context assembly         | Capability → Continuity |\n| `hermes` → `knowledge`    | RAG queries for knowledge hits                | Capability → Continuity |\n| `act` → `pipeline`        | `ExecutionResult` → `PIPELINE_QUEUE`          | Capability → Continuity |\n\n### 12.3 Eastbound: Governance Layer (Layer 5)\n\n| Integration           | Contract                                  | Direction               |\n| --------------------- | ----------------------------------------- | ----------------------- |\n| `hermes` → `govern`   | Proposal + confidence → `GovernanceState` | Capability → Governance |\n| `govern` → `hermes`   | Approval/denial → execution routing       | Governance → Capability |\n| `workflow` → `govern` | HITL pause → approval checkpoint          | Capability → Governance |\n\n### 12.4 Westbound: Provider Fabric (Layer 6)\n\n| Integration                     | Contract                                 | Direction               |\n| ------------------------------- | ---------------------------------------- | ----------------------- |\n| `act` → Provider APIs           | Adapter modules (Nango, MCP, Native)     | Capability → Provider   |\n| `act` → `spine-v2`              | Entity360 injection before outbound call | Capability → Continuity |\n| `connector-sync` → `normalizer` | Raw records → canonical transform        | Provider → Continuity   |\n\n---\n\n## 13. Ecosystem = Capability Fabric\n\n### 13.1 Definition\n\nThe **Ecosystem** is the capability fabric for:\n\n- **Knowledge sharing** — cross-tenant (with consent) and cross-entity knowledge propagation\n- **Tool-to-tool communication** — agents and tools coordinate through Spine, not peer-to-peer\n- **Agent communication** — A2A protocol through shared Spine context\n\n### 13.2 Ecosystem Capabilities\n\n```typescript\n// packages/sdk/src/ecosystem.ts\n\n/**\n * Ecosystem capabilities enable cross-boundary collaboration\n * while maintaining tenant isolation.\n */\nexport interface EcosystemAPI {\n  /**\n   * Broadcast a knowledge packet to the ecosystem.\n   * Knowledge packets are anonymized, scored, and governed before broadcast.\n   */\n  broadcast(tenantId: string, packet: KnowledgePacket): Promise<EcosystemReceipt>;\n\n  /**\n   * Query the ecosystem for relevant knowledge.\n   * Returns knowledge from other tenants (anonymized) + own tenant.\n   */\n  query(tenantId: string, query: EcosystemQuery): Promise<KnowledgeHit[]>;\n\n  /**\n   * Subscribe to ecosystem signals.\n   * Relevant signals from other tenants (anonymized patterns, not raw data).\n   */\n  subscribe(tenantId: string, filter: SignalFilter): Promise<SubscriptionHandle>;\n}\n\nexport interface KnowledgePacket {\n  id: string;\n  tenantId: string; // Source tenant (anonymized in broadcast)\n  category: \"pattern\" | \"insight\" | \"best_practice\" | \"cautionary_tale\";\n  content: string;\n  confidence: number; // Must be ≥ 0.85 for ecosystem broadcast\n  evidence: Evidence[];\n  tags: string[];\n\n  /** Whether this packet can be shared across tenant boundaries */\n  shareable: boolean;\n\n  /** Anonymization level */\n  anonymization: \"full\" | \"partial\" | \"none\";\n}\n```\n\n---\n\n## 14. Service Topology for This Domain\n\n| Service             | Tier   | Binding             | Role in This Domain                                         |\n| ------------------- | ------ | ------------------- | ----------------------------------------------------------- |\n| `hermes`            | Tier 3 | `HERMES`            | Capability Router — Durable Object, execution orchestration |\n| `iw-agent-runtime`  | Tier 3 | `IW_AGENT_RUNTIME`  | MCP-compliant agent execution                               |\n| `workflow`          | Tier 3 | `WORKFLOW`          | Durable orchestration — sagas, retries, HITL pause          |\n| `act`               | Tier 2 | `ACT`               | Outbound execution + adapter modules                        |\n| `mcp-connector`     | Tier 3 | `MCP_CONNECTOR`     | Inbound MCP bridge                                          |\n| `twin-orchestrator` | Tier 2 | `TWIN_ORCHESTRATOR` | Persistent per-user OODA engine (Durable Object)            |\n| `think`             | Tier 4 | `THINK`             | LLM orchestration — OpenRouter abstraction                  |\n| `govern`            | Tier 2 | `GOVERN`            | Confidence gate — approval thresholds                       |\n| `agent-registry`    | Tier 4 | `AGENT_REGISTRY`    | Capability Registry — catalog of all capabilities           |\n| `intelligence`      | Tier 2 | `INTELLIGENCE`      | Context Assembly — Entity360, memory, knowledge             |\n| `knowledge`         | Tier 2 | `KNOWLEDGE`         | RAG, semantic search, document chunking                     |\n| `continuity`        | Tier 4 | `CONTINUITY`        | Memory retrieval, SSOC resolution                           |\n| `normalizer`        | Tier 1 | `NORMALIZER`        | 8-stage canonicalization (Observe → Orient)                 |\n| `pipeline`          | Tier 2 | `PIPELINE`          | **ONLY Spine writer** — all writeback routes here           |\n\n---\n\n## 15. Summary: The Capability Layer in One Diagram\n\n```\n┌─────────────────────────────────────────────────────────────────────────────┐\n│                         CAPABILITY LAYER v2.0                               │\n│                    The OODA Execution Fabric                                │\n├─────────────────────────────────────────────────────────────────────────────┤\n│                                                                             │\n│   NORTH (Layer 2)                                                           │\n│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                        │\n│   │   Gateway   │  │   MCP In    │  │  Webhook    │                        │\n│   │             │  │   (SSE)     │  │  Ingress    │                        │\n│   └──────┬──────┘  └──────┬──────┘  └──────┬──────┘                        │\n│          │                │                │                                │\n│          └────────────────┼────────────────┘                                │\n│                           ▼                                                 │\n│   ┌───────────────────────────────────────────────────────┐                │\n│   │              HERMES — Capability Router               │                │\n│   │              (Durable Object)                         │                │\n│   │                                                       │                │\n│   │  1. RESOLVE ──▶ Registry (KV + D1)                   │                │\n│   │  2. VALIDATE ──▶ Schema + Permissions                 │                │\n│   │  3. ASSEMBLE ──▶ intelligence (Context Assembly)      │                │\n│   │  4. GOVERN ──▶ govern (confidence gate)               │                │\n│   │  5. EXECUTE ──▶ Route to runtime:                     │                │\n│   │     • direct → service binding RPC                    │                │\n│   │     • agent → iw-agent-runtime (MCP)                  │                │\n│   │     • pipeline → PIPELINE_QUEUE → pipeline            │                │\n│   │     • workflow → WORKFLOW DO (saga)                   │                │\n│   │     • mcp → act → MCPOutboundAdapter                  │                │\n│   │                                                       │                │\n│   └───────────────────────────────────────────────────────┘                │\n│                           │                                                 │\n│          ┌────────────────┼────────────────┐                                │\n│          ▼                ▼                ▼                                │\n│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                        │\n│   │    ADK      │  │   Workflow  │  │     Act     │                        │\n│   │   Runtime   │  │   Engine    │  │  + Adapters │                        │\n│   │(twin-orches-│  │(saga,retry, │  │             │                        │\n│   │  trator DO) │  │  HITL pause)│  │ • Nango     │                        │\n│   │             │  │             │  │ • MCP out   │                        │\n│   │ • propose   │  │             │  │ • Native    │                        │\n│   │ • analyze   │  │             │  │             │                        │\n│   │ • predict   │  │             │  │             │                        │\n│   └─────────────┘  └─────────────┘  └──────┬──────┘                        │\n│                                             │                               │\n│   SOUTH (Layer 6)                           ▼                               │\n│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                        │\n│   │  Salesforce │  │    Slack    │  │   GitHub    │  ... Provider Fabric   │\n│   └─────────────┘  └─────────────┘  └─────────────┘                        │\n│                                                                             │\n│   EAST (Layer 4)          │           WEST (Layer 5)                       │\n│   ┌─────────────┐         │         ┌─────────────┐                        │\n│   │  Continuity │◄────────┘         │  Governance │                        │\n│   │  (Spine,    │  (writeback)      │  (0.70/0.85)│                        │\n│   │   Memory)   │                   │             │                        │\n│   └─────────────┘                   └─────────────┘                        │\n│                                                                             │\n│   INVARIANTS:                                                               │\n│   • Pipeline is the ONLY Spine writer                                       │\n│   • Agent NEVER writes to Spine directly                                    │\n│   • Every hop carries tenant_id                                             │\n│   • Twin is AMBIENT — consumers call capabilities, not the Twin             │\n│   • Ecosystem = capability fabric for knowledge + tool + agent comms        │\n│                                                                             │\n└─────────────────────────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 16. Appendix: File Paths and Package Structure\n\n```\npackages/\n├── sdk/                          # Platform SDK — consumer-facing\n│   ├── src/\n│   │   ├── client.ts             # CapabilityClient — HTTP + service binding\n│   │   ├── capabilities.ts       # Typed capability wrappers\n│   │   ├── context.ts            # AssembledContext, Entity360 types\n│   │   ├── contracts.ts          # CapabilityInvocation, CapabilityResponse\n│   │   ├── execution.ts          # ExecutionResult, GovernanceState\n│   │   └── ecosystem.ts          # EcosystemAPI, KnowledgePacket\n│   └── package.json\n│\n├── twin-types/                   # Shared Twin/ADK types\n│   ├── src/\n│   │   ├── adk.ts                # ADKRuntime, Proposal, TwinState\n│   │   ├── proposal.ts           # Proposal + ConfidenceScore\n│   │   ├── governance.ts         # ApprovalState, GovernanceEvent\n│   │   └── memory.ts             # MemoryScope, MemoryTier, DecayRule\n│   └── package.json\n│\n└── mcp-types/                    # Shared MCP schemas\n    ├── src/\n    │   ├── inbound.ts            # Session, Tool, Invoke, Health types\n    │   ├── outbound.ts           # ProviderAdapter, ContextInjection types\n    │   └── guards.ts             # JWT claims, TenantScope, ReadOnlyGate\n    └── package.json\n\nservices/\n├── hermes/                       # Capability Router (Durable Object)\n│   ├── src/\n│   │   ├── index.ts              # DO entry point\n│   │   ├── router.ts             # CapabilityRouter class\n│   │   ├── routing.ts            # RoutingTable, RouteEntry\n│   │   └── circuit-breaker.ts    # Per-provider circuit breaker\n│   └── wrangler.toml\n│\n├── iw-agent-runtime/             # MCP-compliant agent execution\n│   ├── src/\n│   │   ├── index.ts\n│   │   ├── agent.ts              # Agent execution engine\n│   │   └── mcp-server.ts         # MCP server wrapper for agents\n│   └── wrangler.toml\n│\n├── twin-orchestrator/            # Persistent per-user OODA engine\n│   ├── src/\n│   │   ├── index.ts              # DO entry point\n│   │   ├── engine.ts             # OODA engine implementation\n│   │   ├── session.ts            # Session state management\n│   │   └── memory-graph.ts       # In-DO memory graph\n│   └── wrangler.toml\n│\n├── think/                        # LLM orchestration\n│   ├── src/\n│   │   ├── index.ts\n│   │   ├── engine.ts             # ThinkEngine implementation\n│   │   ├── openrouter.ts         # OpenRouter adapter\n│   │   └── model-selector.ts     # Model selection logic\n│   └── wrangler.toml\n│\n├── mcp-connector/                # Inbound MCP bridge\n│   ├── src/\n│   │   ├── index.ts\n│   │   ├── sessions.ts           # Session lifecycle (KV-backed)\n│   │   ├── tools.ts              # Tool catalog assembly\n│   │   ├── invoke.ts             # Capability routing via Hermes\n│   │   └── guard.ts              # JWT verify + tenant_id + read-only gate\n│   └── wrangler.toml\n│\n└── agent-registry/               # Capability Registry\n    ├── src/\n    │   ├── index.ts\n    │   ├── registry.ts             # Registry CRUD + caching\n    │   ├── validation.ts           # JSON Schema validation\n    │   └── discovery.ts            # Discovery response assembly\n    └── wrangler.toml\n```\n\n---\n\n**END OF SPECIFICATION**\n\n_IntegrateWise Continuity Bridge v2.0 — Capability Layer and OODA Runtime. This document is Stage 1/2 of the canonical architecture deep-dive. It feeds into the final v2.0 canonical architecture document._\n"}