{"slug":"architecture/MCP_ADK_ROUTING_SPINE_MEMORY_ARCHITECTURE","title":"IntegrateWise — MCP + ADK + Routing + Spine Cache + Memory Architecture","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/MCP_ADK_ROUTING_SPINE_MEMORY_ARCHITECTURE.mdx","bytes":45295,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n> **Date:** 2026-06-09 | **Authority:** Nirmal (Founder) | **Version:** 1.2\n> **Status:** Canonical | LIVE — MCP server (20 tools), Spine, and memory loop responding\n> **Scope:** The read/consumption stack and the governed write stack, end to end.\n> Companion to `docs/ARCHITECTURE_AND_DATA_FLOW.md` (system-wide flow) and\n> `ARCHITECTURE_DECISIONS.md` (decision log).\n\n---\n\n## Changelog\n\n**v1.2 (2026-06-09) — Codebase Mapping & Implementation Status**\n\n- Mapped the architectural layers (ADK, MCP, Spine, Registry Cache, A2A/LLM Communication, Session Logs, and Voice) to their actual locations in the repository.\n- Documented implementation status and client/server mechanics for each component.\n\n**v1.1 (2026-06-09) — Clarified Canonical Architecture**\n\n- Completed Sections 3–8 covering the governed write flow and execution path.\n- Clarified Supabase is **usage-allocated** (promoted tenants only). Initial users run edge-only on D1; Supabase is a usage-earned durability upgrade, not a base dependency. Added §7.7 Tenant storage tiers.\n- Standardized the canonical tool count to **20** across all architecture documents.\n- Clarified the Continuity Bridge ↔ MCP relationship:\n  - MCP is the interface.\n  - Continuity Bridge is the composed product.\n  - Internal access via `continuity-tool-server`.\n  - External access via `mcp.integratewise.ai`.\n- Clarified ADK placement above Gateway:\n  - Stateless capability resolution only.\n  - No tenant access. No data access. No I/O before Gateway authorization.\n- Clarified Gateway responsibility:\n  - Request assembly (auth + tenant + policy envelope).\n  - Data context remains the responsibility of Spine Cache.\n- Removed duplicate explanatory notes introduced during parallel edits.\n- Aligned the architecture narrative with the rendered system diagram.\n\n**v1.0 — Initial Canonical Architecture**\n\n- Layered model, hard boundaries, and the five walls.\n\n---\n\n## 0. The One Sentence\n\nThe LLM never reads from tools. The LLM never reads from Main Memory.\nThe LLM only ever reads from **Spine Cache**, assembled on demand from Main\nMemory, delivered via **MCP**, resolved by the **ADK** against the tenant's\nschema. Tools push to Spine once. Agents pull from Spine forever.\n\n> The product is the **IW Continuity Bridge**. MCP + ADK + Gateway + Spine\n> Cache + Memory are the layers that make the Bridge work. Connect an AI to the\n> Bridge once; every authorized source becomes normalized, governed, and\n> remembered. M×N tool connections collapse to 1:N.\n\n---\n\n## 1. The Layered Model (canonical)\n\nTwo directions of flow over the same layers. Read them separately.\n\n```\n              ┌────────────────────────────────────────────┐\n              │                   LLM                       │\n              │   (Twin runtime — Open WebUI, model-        │\n              │    agnostic: Grok / Claude / GPT / local)   │\n              └─────────────────────┬──────────────────────┘\n                                    │\n              ┌─────────────────────▼──────────────────────┐\n              │                   ADK                       │\n              │   Capability resolution. Planning hints.    │\n              │   Stateless. No memory. Zero I/O.           │\n              └─────────────────────┬──────────────────────┘\n                                    │\n              ┌─────────────────────▼──────────────────────┐\n              │                 GATEWAY                     │\n              │   Auth · Policy · Routing · Rate limiting   │\n              │   Tenant resolution · Request assembly      │\n              └─────────────────────┬──────────────────────┘\n                                    │\n              ┌─────────────────────▼──────────────────────┐\n              │           MCP INTERFACE (3 channels)        │\n              │   Memory MCP   Session MCP   Tool MCP       │\n              └─────────────────────┬──────────────────────┘\n                                    │\n              ┌─────────────────────▼──────────────────────┐\n              │                SPINE CACHE                  │\n              │   Prepared AI data context (fast, <10ms)    │\n              │   D1 edge · KV · Vectorize / AI Search      │\n              └─────────────────────┬──────────────────────┘\n                                    │\n              ┌─────────────────────▼──────────────────────┐\n              │                MAIN MEMORY                  │\n              │   Durable record of truth (never queried    │\n              │   directly by agents)                       │\n              │   Supabase (fortress) · R2 (raw) ·          │\n              │   D1 metadata · filesystem vault            │\n              └─────────────────────────────────────────────┘\n```\n\n- **CONSUMPTION PATH (LLM reads context):**\n  `Main Memory → Spine Cache → MCP → Gateway → ADK → LLM`\n- **WRITE PATH (data + knowledge enters):**\n  `Tool → Nango → Connector → Loader → Normalizer → [Governance] → Main Memory + Spine Cache → MCP invalidation`\n\nThe Gateway is **first** on the inbound (write) direction and **between MCP and\nADK** on the outbound (LLM-initiated) direction. Both are correct; they are\ndifferent directions of the same pipe.\n\n> **How this maps to the IW Continuity Bridge.** This document describes the\n> _internal composition_ of the Bridge. The Twin's runtime client — the\n> `continuity-tool-server` — is what speaks the Memory/Session MCP channels into\n> `services/pipeline` and the Spine Cache. So \"the LLM reads via MCP\" (this doc)\n> and \"the Twin reads via the IW Continuity Bridge\" (`ARCHITECTURE_AND_DATA_FLOW.md`)\n> are the same statement at two levels of zoom: MCP is the _interface_, the\n> Continuity Bridge is the _composed product_. The public `mcp.integratewise.ai`\n> endpoint is the same interface exposed to **external** agents (Claude, ChatGPT)\n> that live outside the Bridge.\n\n**ADK before Gateway is safe.** On an LLM-initiated call the first hop is ADK,\nwhich sits \"above\" Gateway in the diagram. ADK does zero I/O and holds no state —\nit only resolves a capability name to an implementation and emits planning hints.\nNo tenant data is touched and no side effect occurs until the request crosses the\nGateway, where auth, tenant resolution, and policy are enforced. Capability\nresolution on an unauthenticated request reveals nothing and changes nothing.\n\n**The Bridge ↔ MCP relationship (reconciles `ARCHITECTURE_AND_DATA_FLOW.md`).**\nThe product is the IW Continuity Bridge. MCP is the _internal interface_ the\nBridge exposes; it is not a separate product. The Twin reaches this interface\nthrough its `continuity-tool-server`, which is the Twin's MCP/Session client into\nthe Bridge (`continuity-tool-server → pipeline → Spine Cache`). The public\nendpoint `mcp.integratewise.ai` is the _same interface_ exposed to EXTERNAL\nagents (Claude, ChatGPT). So: Twin → Continuity Bridge (internal MCP/Session\nchannel); external agents → `mcp.integratewise.ai` (public MCP). One interface,\ntwo doors. No contradiction.\n\n---\n\n## 2. Layer Responsibilities (hard boundaries)\n\n```\nMAIN MEMORY        Durable, governed, versioned, complete. Append-oriented.\n                   Never queried directly by an LLM or agent.\n                   = R2 (raw content, backups, spine-backup JSONL)\n                   + D1 (durable metadata + record of truth for edge-only tenants)\n                   + filesystem vault (.iw-memory dual-write)\n                   + Supabase (fortress) — USAGE-ALLOCATED, promoted tenants only\n                     (see §7.7; initial users do NOT get Supabase)\n\nSPINE CACHE        Prepared DATA context built for agent consumption. Fast (<10ms).\n                   Rebuildable from Main Memory. Safe to evict.\n                   = D1 edge (spine_vault, encrypted) + KV (hot) + Vectorize/AI Search\n\nMCP INTERFACE      Three channels, one protocol. The only surface an agent calls.\n                   Memory MCP · Session MCP · Tool MCP.\n\nGATEWAY            Auth, policy enforcement, routing, rate limiting, tenant\n                   resolution, REQUEST assembly (auth + tenant + policy envelope).\n                   NOT governance. NOT data context (that is Spine Cache).\n\nADK                Capability → implementation resolution. Schema validation\n                   for spine.entity.*. Stateless. Zero I/O. No persistent memory.\n\nLLM / TWIN         Reasoning runtime. Reads Spine Cache only. Proposes, never\n                   writes to Spine. Model is a parameter.\n```\n\n**The walls that must never be crossed:**\n\n1. LLM ↔ Tools: NEVER direct (once a tool is connected, Spine is the query target).\n2. LLM ↔ Main Memory: NEVER direct (only Spine Cache).\n3. ADK ↔ State: NEVER (ADK is stateless; planning is hints, not memory).\n4. Agent ↔ Spine write: NEVER direct (propose → govern → Pipeline writes).\n5. Chat ↔ Approval: NEVER. Approval is the **U4 Decide** stage; its UI is surfaced\n   on the **S2 Awareness** surface, never in S3 Twin chat/voice — chat is not an audit trail.\n\n---\n\n## 3. MCP Interface — Three Channels\n\nMCP is not one thing. Memory queries, session-state queries, and tool execution\nare fundamentally different operations that happen to share a protocol.\n\n```\nMEMORY MCP        Reads institutional knowledge. Semantic.\n                  Source: Vectorize / AI Search (inside Main Memory).\n                  Tools: memory.search_org, memory.read_conversational,\n                         memory.read_personal\n                  Caching: NONE for org memory reads — always fresh\n                  (post-promotion entries must be visible immediately).\n\nSESSION MCP       Reads current working state. Operational.\n                  Source: KV + D1 (Spine Cache).\n                  Tools: signal.list, spine.entity.get, spine.entity.list,\n                         spine.entity.search, task.list\n                  Caching: KV hot cache, 30–300s TTL.\n\nTOOL MCP          Executes capabilities. Governed.\n                  Tools: memory.propose, memory.write_conversational,\n                         proposal.approve*, proposal.reject*, task.dispatch,\n                         connector.write, book.*, kb.*\n                  Writes route through governance. Never direct to Spine.\n                  (* approval EXECUTION is governed; the approval DECISION UI\n                     is L2-only, never chat — see §2 wall 5.)\n```\n\n### MCP access (live) — Native OAuth 2.0 (deployed June 9, 2026)\n\n```\nEndpoint:       https://mcp.integratewise.ai\nProtocol:       POST /  = MCP JSON-RPC protocol (no /mcp suffix needed)\n                GET /   = server info\n\nOAuth Discovery: https://mcp.integratewise.ai/.well-known/oauth-authorization-server\nToken Endpoint:  https://mcp.integratewise.ai/oauth/token\nJWKS:            https://mcp.integratewise.ai/.well-known/jwks.json\n\nGrant Types:    authorization_code, client_credentials, refresh_token\nToken Format:   RS256 JWT (1hr access, 30d refresh)\nScopes:         mcp:tools, mcp:resources, tenant:read, tenant:write, memory:read, memory:write\nClient Registry: D1 oauth_clients table (integratewise-spine-cache)\nScope Enforcement: per-tool filtering in oauth-scopes.ts\n\nTool count:     20 (memory.* · spine.* · signal.* · task.* · proposal.* · book.* · kb.*)\n```\n\nAny MCP-compatible AI client (Claude, ChatGPT, Cursor, Kiro, Perplexity) connects\nvia standard OAuth 2.0. No CF-Access-Client-Id/Secret workaround required — the\nMCP server now implements native OAuth endpoints directly.\n\n> **SECURITY:** OAuth client secrets and signing keys are referenced by name only.\n> They live in Cloudflare Secrets Store (D1 for client registry). Never commit\n> secret values, never echo them in chat or logs.\n\n### Token exchange gate\n\nThe Gateway validates RS256 JWT tokens at the edge for `mcp.integratewise.ai`\ntraffic, enriches headers (tenant, scopes), and forwards to the MCP connector via\nservice binding. This enforces the capability contract at the protocol boundary —\npreventing an agent from bypassing the ADK and hitting a service directly.\n\n---\n\n## 4. Gateway — Policy, Not Governance\n\n```\nGATEWAY DOES:\n  • Auth: validate RS256 JWT (OAuth 2.0 tokens from mcp.integratewise.ai)\n  • Tenant resolution: inject x-tenant-id on every downstream call\n  • Policy enforcement: is THIS agent authorized to see THIS data? (plan tier)\n  • Routing: bind to downstream workers (pipeline, intelligence, knowledge, connector)\n  • Rate limiting\n  • Context assembly: stitch Entity 360 (Spine + Memory + Signals) for a read\n\nGATEWAY DOES NOT:\n  • Govern memory promotion (that's Triage Bot / Governance layer)\n  • Write to Spine (that's Pipeline)\n  • Hold tool credentials (those are in Nango)\n```\n\n### Resilience (single-point mitigations)\n\n```\n  • CF Workers global redundancy: 300+ edge locations, stateless by design\n  • KV-cached tenant resolution: buffers a D1 hiccup\n  • On binding timeout: return 503 + Retry-After; ADK circuit breaker trips\n  • Fallback read path exists at the ADK layer (see §5 fallback chain)\n```\n\n---\n\n## 5. ADK — The Capability Resolver (the MuleSoft of AI)\n\nMuleSoft: stable API contract (RAML) + swappable routing (Anypoint) + changing\nbackends. IntegrateWise applies the same one layer up: stable **capability\ncontract** (MCP tools) + swappable routing (ADK) + changing Spine/Memory/services.\n\nThe client declares a _capability it needs_; it never names an implementation.\nIf storage or a connector changes, the ADK resolves differently and the client\nis unchanged. The contract holds.\n\n### 5.1 Capability grammar\n\n```\nFormat:  <domain>.<resource>.<operation>\n\ndomain      ∈ { spine, memory, signal, task, proposal, connector }\nresource    ∈ { entity, memory, signal, task, proposal, connector }\noperation   ∈ { get, list, search, create, write, propose,\n                approve, reject, dispatch }\n\nExamples:\n  spine.entity.get        spine.entity.list     spine.entity.search\n  spine.entity.create     memory.search_org     memory.propose\n  memory.write_conversational                    signal.list\n  task.dispatch           proposal.approve       proposal.reject\n  connector.write\n```\n\nSchema validation (§5.4) applies to `spine.entity.*` ONLY. `memory.*`,\n`signal.*`, `task.*`, `proposal.*` are schema-agnostic and bypass it.\n\n### 5.2 Resource types (8)\n\n```\n1. entity      Person, Company, Opportunity, Account, ...\n2. activity    Calls, emails, meetings, touches\n3. event       State changes, webhooks, transitions\n4. metric      ARR, health, scores, counts\n5. file        R2 objects (documents, attachments)\n6. task        Work items, dispatched jobs\n7. proposal    Governance queue items\n8. memory      Governed Vectorize/AI Search entries\n               (distinct from file: different storage, governance, retrieval;\n                reads ALWAYS fresh — never KV-cached)\n```\n\n### 5.3 Route destination types (4)\n\n```\nLOCAL_D1        D1 edge read (Spine Cache). entity/signal/task lookups.\nVECTOR_INDEX    Vectorize / AI Search. memory.* semantic reads.\nREMOTE_WORKER   Service binding (intelligence, knowledge, connector).\nNANGO_PROXY     Live pass-through to a tool via Nango token (rare; write/act).\n```\n\n### 5.4 Schema binding — dynamic, not static\n\nThe ADK binds to the existing schema system in `@integratewise/types`\n(`DOMAIN_SPINE_CONFIG` + `INDUSTRY_SPINE_BASE` via `SchemaAccessor`):\n**12 departments × 11 industry overlays, 130+ canonical entity types.**\n\n> Superseded: the early static \"8 resource types × 18 traits\" model was\n> CS-biased. Traits are now the `priority_fields` of each canonical entity type,\n> resolved per the active tenant's department + industry. One schema definition,\n> one place to update, all departments inherited automatically. (This is the\n> DataWeave equivalent — the repeatable normalization IP.)\n\n```\nv1 resolution mode: static.\n  SchemaAccessor() with no KV/DB params resolves from DOMAIN_SPINE_CONFIG +\n  INDUSTRY_SPINE_BASE in-process. Zero network cost. Schema changes ship on\n  redeploy. resolveSchema(tenantId, department, industry) is async by\n  signature but resolves synchronously in static mode.\n\n  IMPORTANT: resolveSchema MUST apply BOTH the department config AND the\n  industry overlay. A Healthcare CS tenant must not be validated against the\n  SaaS CS schema. Cross-industry overlay is mandatory (see test matrix §10).\n```\n\n### 5.5 Field policy\n\n```\nREADS:   STRIP fields not in the tenant's priority_fields from the response.\nWRITES:  REJECT (400) unknown fields in the write payload.\n         Prevents context pollution at the ingress point.\n```\n\n### 5.6 Resolution algorithm\n\n```\n1. Parse capability → { domain, resource, operation }\n2. Load tenant config from KV (5-min TTL): plan_tier, domain_key, industry_overlay\n3. PLAN GATE: plan_tier >= capability.min_tier ?\n      No  → 403 PLAN_INSUFFICIENT { upgrade_url }\n4. SCHEMA (spine.entity.* only):\n      schema = SchemaAccessor.resolveSchema(tenant, domain_key, industry_overlay)\n      validate entity_type ∈ schema ; filter/reject fields per §5.5\n5. CONNECTOR STATUS (capabilities needing a connector):\n      not_connected   → 403 CONNECTOR_NOT_AVAILABLE { connect_url }\n      syncing_initial → 202 CONNECTOR_SYNCING { syncing:true, progress, data:nulls }\n      sync_complete   → proceed\n6. ROUTE to destination (LOCAL_D1 → ... → fallback chain)\n7. Return typed CapabilityResponse\n```\n\n### 5.7 Fallback chain (reads)\n\n```\nD1 index lookup → D1 full scan → Supabase (PROMOTED tenants only) → 404\n  (Pipeline is NEVER a read fallback — it is the write service only.)\n```\n\n### 5.8 Tiered TTL\n\n```\nCapability registry (what capabilities exist)     24h    — changes on deploy\nTenant capability config (what this tenant can do) 5min   — changes on upgrade/connect\nCONNECTOR_STATUS (what's live right now)           30s    — changes during sync\nOrg memory reads                                   none   — always fresh\n```\n\n### 5.9 Failure taxonomy (every consumer handles these identically)\n\n```\n404 CAPABILITY_NOT_FOUND     Not in registry. Do not retry.\n403 PLAN_INSUFFICIENT        Tier too low. Response carries upgrade_url.\n403 CONNECTOR_NOT_AVAILABLE  Not connected. Response carries connect_url.\n202 CONNECTOR_SYNCING        Connected but syncing_initial. Cached/placeholder\n                             data + syncing:true. NEVER fabricated metrics —\n                             computed fields are null with a \"syncing\" note.\n503 RESOLVER_DEGRADED        KV + D1 fallback failed. Retry-After header.\n                             Gateway circuit breaker trips.\n```\n\n### 5.10 Min-tier map (capability gating)\n\n```\nFREE:       spine.entity.get/list (read-only, limited routes), 1 connector\nSTARTER:    + signal.list, basic Twin (Mode A), 3 connectors\nPRO:        + memory.search_org, memory.propose, proposal.*, connector.write,\n            CF Workflows, full Twin (Mode B), unlimited connectors, full memory\nENTERPRISE: + external LLM MCP endpoint per tenant, custom domain, multi-workspace\n```\n\n> `connector.write` min_tier = **pro** (NOT enterprise). Pro users must be able\n> to execute approved Twin proposals or the governance loop breaks for the\n> largest non-enterprise segment. Enterprise gates the external MCP endpoint.\n\n---\n\n## 6. Spine Cache — Prepared Context\n\nSpine Cache is everything between Main Memory and the MCP interface. It exists\nso the LLM gets sub-10ms, normalized, assembled context without ever touching\nthe durable record.\n\n```\nD1 (integratewise-spine-cache)   Read-optimized Spine + Memory mirror.\n  spine_vault                    Entities, encrypted (AES-256-GCM, opaque k,v,t,c).\n                                 SPINE_ENCRYPTION_KEY in CF Secrets.\n  org_memory (metadata)          governance_state: staging|approved|published\n  conversational_memory          Twin chat sessions\n  signals                        time-ordered state changes\n  tenant_spine_config            per-tenant entity manifest (from onboarding)\n\nKV\n  CACHE                          hot entity cache, 60–300s\n  SIGNAL_CACHE                   signal cache\n  METRICS                        counters\n  (tenant resolution cache)      buffers D1 hiccups\n\nVectorize / AI Search            semantic index over governed memory\n  AI_SEARCH (bge-base, free)     auto-embed; the Twin's institutional recall\n```\n\n**Entity 360** is the assembly moment: Spine (operational truth from D1) +\nMemory (institutional knowledge from Vectorize/AI Search) + Signals (time-ordered\nrecent events) composed into one session view, served via Session MCP.\n\n```\nSpine wins on conflict. If a cache mirror (e.g. an OWUI Knowledge collection)\ndisagrees with org_memory in D1/Supabase, the durable record is correct.\nCache layers are retrieval accelerators, never sources of truth.\n```\n\n### CONNECTOR_STATUS state machine\n\nThe cache's freshness depends on connector lifecycle. The frontend and the ADK\nboth read this.\n\n```\nnot_connected\n   → oauth_pending          (Nango flow open)\n   → oauth_complete         (token held; first sync not started)\n   → syncing_initial        (creamy layer: 5 records in flight — show progress)\n   → sync_complete          (Spine has data — dashboard/Entity 360 may load)\n   → syncing_delta          (background 5-min cron — transparent to user)\n   → sync_error             (failed — surface which stage)\n\nStored in KV CONNECTOR_STATUS. \"connected\" and \"data-populated\" are different\nstates — this distinction prevents the \"connected but empty Entity 360\" bug.\n```\n\n---\n\n## 7. Memory Architecture\n\n### 7.1 Three memory types\n\n```\nconversational_memory   Raw sessions (Twin, external LLM, manual). role: user|assistant|system.\n                        THE SOURCE. Everything else derives from here.\norg_memory              Promoted institutional knowledge — DERIVED from conversational_memory\n                        via propose → govern (§7.2). NEVER written directly.\n                        governance_state: staging|approved|published.\npersonal_memory         Behavioral patterns. category: preference|behavior|context|decision.\n\nLineage (one direction):\n  conversation → conversational_memory → propose → Triage → org_memory\n              → (projection) → docs / Entity 360 / AI Search index\n  org_memory is always a governed promotion of conversational_memory. No agent or\n  human writes org_memory directly; it is earned through governance.\n\nAll: tenant_id isolation · pgvector / Vectorize similarity.\nEdge-only tenants: these live in D1 + Vectorize. Promoted tenants additionally\nmirror to Supabase memory.* (RLS-enabled) as the durable record. See §7.7.\n```\n\n### 7.2 The memory loop (Flow C — governed)\n\n```\n1. CAPTURE   Any conversation → memory.write_conversational → conversational_memory\n2. IDENTIFY  Twin spots something worth keeping (decision, pattern, commitment, learning)\n3. PROPOSE   memory.propose → proposals (D1) → Triage Bot queue\n4. GOVERN    Triage Bot scores (confidence · relevance · risk · conflict · quality):\n                ≥ 0.85          → auto-approve\n                0.60 – 0.84     → HITL (human review in L2)\n                < 0.60          → reject\n5. STORE     Approved → DUAL-WRITE to:\n                R2 (raw) + AI Search (embedded) + D1 (record of truth) + filesystem vault (.iw-memory)\n                + Supabase org_memory — ONLY for promoted tenants (see §7.7)\n6. RETRIEVE  Next session: Twin reads via Memory MCP (semantic). Entity 360 intersects with Spine.\n\nLOOP CLOSES. Knowledge compounds. Nothing starts cold.\n```\n\n### 7.3 Personal memory auto-promotion (precise rule)\n\n```\nCandidate surfaces when the SAME behavioral pattern appears in 5+ DISTINCT\nsessions within a rolling 30-day window, at confidence ≥ 0.70. Then it enters\nthe propose → govern path like any other promotion. (Not \"after 5 sessions.\")\n```\n\n### 7.4 Initial / bulk load scoring (not flat 0.85)\n\n```\nRun a cleaner pass FIRST (normalize, extract, quality-score). Then base\nconfidence by document category, not a blanket value:\n  architecture/  → 0.90   transcripts/ → 0.70   notes/ → 0.75\nPropose only above a quality threshold. Route via BULK_MEMORY_QUEUE\n(separate from pipeline-process; max ~10 concurrent; lower priority than live\nops) so bulk promotion never creates backpressure on the live loop.\n```\n\n### 7.5 No-archive rule (constitutional)\n\n```\nThe Knowledge Store has no archive folder. Content is:\n  • active, or\n  • superseded (with lineage to the superseding entry), or\n  • rejected (with reason).\nAI may never dump content into an archive. It proposes UPDATE or SUPERSEDE —\nnever hides content. (Constitutional rule D-2026-06-05-013.)\n```\n\n### 7.6 Durability & repair (Main Memory)\n\n```\nD1-FIRST tenants (edge-only): Pipeline appends every Spine write to\n   R2: spine-backup/{tenant_id}/{date}.jsonl  → replay path if D1 is lost.\n   (Define retention: e.g. 30 daily snapshots, weekly beyond.)\n\nPROMOTED tenants: D1 rebuildable from Supabase fortress.\n\nREINDEX JOB (R2 ↔ Vectorize consistency — runs both directions):\n   FORWARD: R2 keys missing from Vectorize → re-chunk, re-embed, re-index.\n   REVERSE: Vectorize memory_ids missing from R2 → reconstruct if possible,\n            else flag \"orphaned — content unrecoverable\" for human review.\n   Idempotent. Trigger: daily cron (owning worker pinned) + on-demand admin endpoint.\n```\n\n### 7.7 Tenant storage tiers — Supabase is usage-allocated, not default\n\nSupabase (the fortress / durable relational record of truth) is **not** handed to\nevery tenant. It is **allocated based on usage**. Initial users run entirely on the\nCloudflare edge; Supabase is provisioned only when a tenant is **promoted**.\n\n```\nEDGE-ONLY (default — every new / initial user):\n  Storage:   D1 (record of truth for this tenant) + KV + R2 (spine-backup JSONL)\n             + Vectorize / AI Search (memory).\n  Supabase:  NONE. Not provisioned. Not required.\n  Durability: R2 spine-backup/{tenant_id}/{date}.jsonl is the replay path.\n  Rationale: low cost, instant, full product works at the edge.\n\nPROMOTED (usage-allocated — graduated tenants):\n  Trigger:   crossing a usage threshold — data volume, retention need,\n             compliance/audit requirement, or plan tier (typically Pro+).\n  Storage:   EDGE-ONLY stack, PLUS Supabase (memory.* + relational fortress)\n             added as the durable record of truth + cross-region sync.\n  Durability: D1 becomes rebuildable from the Supabase fortress.\n  Writes:    dual-write begins (edge + Supabase via the CF MCP Worker, the\n             sole Supabase credential holder).\n\nPROMOTION (one-way, governed):\n  Edge-only → Promoted is a backfill: replay R2 spine-backup + D1 into Supabase,\n  then enable dual-write. No tenant is downgraded automatically.\n```\n\n> **Rule:** never describe Supabase as a dependency of the base product. The base\n> product is edge-native. Supabase is a usage-earned durability upgrade. An\n> edge-only tenant is fully functional with zero Supabase footprint.\n\n```\nPipeline is the sole writer to SPINE tables.\nTenants service writes TENANT / USER / WORKSPACE tables.\nTriage Bot writes MEMORY METADATA tables.\nNo other service writes to D1 for any purpose.\n\nAll Spine writes terminate at the CF MCP Worker — the ONLY holder of the\nSupabase credential. Writes go: CF Worker → CF MCP Worker → Supabase → propagate to D1/KV.\n```\n\n---\n\n## 9. The Spine Abstraction Principle (the moat)\n\n```\nBEFORE:  Claude → Tool A (direct, stateless), Claude → Tool B (direct) ...\n         3 agents × 10 tools = 30 connections. No shared truth. No memory.\n\nAFTER:   All tools → Spine (normalize once).\n         Claude → Spine (never touches the tool).\n         Any agent → Spine via the Continuity Bridge.\n         10 tools × 1 Spine = 10 connections, forever. One truth, shared memory.\n\nCONTINUITY BRIDGE WEDGE:\n  An AI already connected to N tools connects to the Bridge ONCE. Every\n  AUTHORIZED source it touches becomes normalized + governed + remembered.\n  No migration. No tool replacement. One connection improves everything.\n\nCASE TREE (agent asks \"what is Acme's MRR?\"):\n  Connected, in Spine        → MCP → ADK → D1 → answer (<10ms). Tool untouched.\n  Connected, sync 8m old     → KV cache returns last-synced state. Spine is truth.\n  NOT connected              → 403 CONNECTOR_NOT_AVAILABLE { connect_url }.\n                               Agent CANNOT route around Spine to the tool.\n  Connected, unauthorized    → 403 PLAN_INSUFFICIENT { upgrade_url }.\n\nTool identity dies at the Normalizer. After Stage 8, the source tool name no\nlonger exists in the data. Spine stores the nature, not the label.\n```\n\n---\n\n## 10. Build & Verification\n\n### 10.1 Build order (do not invert)\n\n```\nPhase 1  packages/adk/          CapabilityRequest/Response, RouteResolver,\n                                KV cache wrapper (3 TTL tiers), CapabilityResolver.\n                                Static SchemaAccessor binding. Unit tests pass.\nPhase 2  services/gateway/      Resolver middleware. plan_tier gate.\n                                Intercept /api/v1/capabilities/* and MCP /tools.\n                                Inject validated headers; prune/reject per §5.5.\nPhase 3  Fallback modes         CONNECTOR_STATUS handling; D1 index → scan →\n                                Supabase (promoted) → 404 chain.\nPhase 4  E2E                    Live connector via NANGO_PROXY vs D1 cache hit.\n```\n\nGateway middleware comes ONLY after the package builds clean and tests pass.\n\n### 10.2 Cross-industry test matrix (mandatory)\n\n```\nCUSTOMER_SUCCESS × SAAS        → standard CS entities + priority_fields\nCUSTOMER_SUCCESS × HEALTHCARE  → patient/provider entities (overlay applied)\nFINANCE × SAAS                 → subscription / MRR entities\nFINANCE × RETAIL               → inventory / POS entities\n```\n\nPassing all four proves `resolveSchema` applies the industry overlay, not just\nthe department config.\n\n### 10.3 End-to-end demo checks (Twin via MCP)\n\n```\n1. \"What is the Spine Abstraction Principle?\"   → Memory MCP (org/AI Search)\n2. \"What ADK decisions were made?\"              → org_memory governance entries\n3. \"What is Acme's health score?\"               → Session MCP → Spine D1\n4. \"Good morning, brief me.\"                    → Entity 360 assembly (Spine+Memory+Signals)\n```\n\n---\n\n## 11. Live State & Codebase Mapping (as of June 9, 2026)\n\nThe architecture is fully implemented across the following codebase locations:\n\n### 11.1 Component Directory Map\n\n| Architectural Layer           | Implementation Directory                                                                        | Active Status | Files & Entrypoints                                                                                                                                                                                              |\n| :---------------------------- | :---------------------------------------------------------------------------------------------- | :------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **ADK (Capability Resolver)** | [packages/adk](file:///Users/nirmal/Github/integratewise-live/packages/adk)                     | Fully Active  | [`registry.ts`](file:///Users/nirmal/Github/integratewise-live/packages/adk/src/registry.ts), [`resolver.ts`](file:///Users/nirmal/Github/integratewise-live/packages/adk/src/resolver.ts)                       |\n| **MCP Tool Server**           | [services/mcp-connector](file:///Users/nirmal/Github/integratewise-live/services/mcp-connector) | Fully Active  | [`index.ts`](file:///Users/nirmal/Github/integratewise-live/services/mcp-connector/src/index.ts), [`tools.ts`](file:///Users/nirmal/Github/integratewise-live/services/mcp-connector/src/handlers/tools.ts)      |\n| **Registry & Spine Cache**    | [packages/adk/src](file:///Users/nirmal/Github/integratewise-live/packages/adk/src)             | Fully Active  | [`agent-registry.ts`](file:///Users/nirmal/Github/integratewise-live/packages/adk/src/agent-registry.ts), [`spine-cache.ts`](file:///Users/nirmal/Github/integratewise-live/packages/adk/src/spine-cache.ts)     |\n| **Spine & Normalizer**        | [services/pipeline](file:///Users/nirmal/Github/integratewise-live/services/pipeline)           | Fully Active  | Normalizer pipeline [`src/index.ts`](file:///Users/nirmal/Github/integratewise-live/services/pipeline/src/index.ts), [`src/spine/`](file:///Users/nirmal/Github/integratewise-live/services/pipeline/src/spine/) |\n| **Session Logs & Events**     | [services/continuity](file:///Users/nirmal/Github/integratewise-live/services/continuity)       | Fully Active  | [`src/index.ts`](file:///Users/nirmal/Github/integratewise-live/services/continuity/src/index.ts), `memory.session_events` in Supabase/D1                                                                        |\n| **LLM Communication**         | [packages/lib](file:///Users/nirmal/Github/integratewise-live/packages/lib)                     | Fully Active  | Universal provider wrapper [`src/ai-provider.ts`](file:///Users/nirmal/Github/integratewise-live/packages/lib/src/ai-provider.ts)                                                                                |\n| **A2A Communication**         | [services/intelligence](file:///Users/nirmal/Github/integratewise-live/services/intelligence)   | Fully Active  | Sync delegate [`agents/index.ts`](file:///Users/nirmal/Github/integratewise-live/services/intelligence/src/agents/index.ts), work-flows, and `http/mcp` client invocations                                       |\n| **Voice Interface**           | External (twin.integratewise.ai)                                                                | Fully Active  | Managed via L3 Open WebUI + Grok-4.3 + Kokoro TTS / Whisper STT                                                                                                                                                  |\n\n### 11.2 Verification Details\n\n- **mcp.integratewise.ai:** Native OAuth 2.0 (RS256 JWT). POST / = MCP JSON-RPC protocol. OAuth discovery at `/.well-known/oauth-authorization-server`. Any MCP-compatible AI client connects via standard OAuth.\n- **gateway.dev.integratewise.ai:** Active, routing all downstream services using D1/KV context enrichment.\n- **packages/adk:** Unit tests and schema validator (`SchemaAccessor` with DOMAIN_SPINE_CONFIG) check out cleanly.\n- **memory.read_conversational & search_org:** Integrated with Supabase/D1 and Vectorize semantic index.\n\nWATCH ITEMS:\n• OAuth client secrets: rotate via D1 oauth_clients table; RS256 signing key via CF Secrets Store.\n• AI_SEARCH binding on pipeline: confirm full org-memory embed (paginate the\nbulk reindex; partial index is worse than none).\n• Frontend VITE_API_BASE_URL = https://gateway.dev.integratewise.ai (real Spine, no seed).\n• R2 backup retention policy + reindex job owner/cron — pin before GA.\n\n---\n\n## 12. Decisions Referenced\n\n```\nD-2026-06-04-003..006   ADK capability resolver (capability→implementation)\nD-2026-06-05-006        ADK binds DOMAIN_SPINE_CONFIG, not static 8×18\nD-2026-06-05-007        connector.write min_tier = pro\nD-2026-06-05-012        Unified agent memory referencing + fallback hierarchy\nD-2026-06-05-013        No-archive rule (active / superseded / rejected only)\nD-2026-06-06-003        Governance hard rule — approve UI in L2, never chat\n```\n\n---\n\n_Normalize once, render anywhere. The LLM only ever sees Spine Cache._\n_One Twin. One Spine. One Memory. One Bridge. One Loop._\n\n---\n\n## 3. The MCP Interface — Three Channels, One Protocol\n\nMCP is the only surface an agent ever calls. It is split into three channels by\nconcern. All three share the same auth, the same tenant isolation, and the same\n\"read from Spine Cache, propose into governance\" contract.\n\n```\nMEMORY MCP      Durable knowledge. Org memory, learnings, doctrine, decisions.\n                Read: assembled from Spine Cache (semantic via AI Search).\n                Write: PROPOSE only → Triage Bot → governed path.\n\nSESSION MCP     Conversational continuity. The \"did we talk about this\" channel.\n                Read: prior turns, session summaries, personal patterns.\n                Write: append conversational turns (low-stakes, not governed).\n                This is the Twin's continuity-tool-server channel.\n\nTOOL MCP        Capability invocation. \"Do a thing in the world.\"\n                Read: entity state from Spine Cache (spine.entity.get, signal.list).\n                Write: NEVER direct to Spine. Emits a PLAYBOOK or a PROPOSAL.\n                Execution boundary applies (customer agent runs the playbook).\n```\n\n**Channel rules:**\n\n- A read on any channel is served from **Spine Cache**, never Main Memory, never a tool.\n- A write on Memory/Tool MCP is a **proposal**, not a commit. Only the Pipeline writes.\n- Session MCP appends are the one low-stakes write that skips governance (they are\n  conversational record, not institutional truth) but they still never touch Spine.\n- All three channels are tenant-scoped by the `x-tenant-id` injected at the Gateway.\n\n---\n\n## 4. ADK — Capability Resolution (stateless)\n\nThe ADK (`@integratewise/adk`) turns a stable **capability name** into a concrete\n**implementation** at call time. Tools change; capabilities do not.\n\n```\nLLM asks for:        capability = \"entity.health.assess\"\nADK resolves:        → implementation bound to tenant schema + plan tier\n                     → returns { tool_ref, schema, planning_hints }\nADK does NOT:        call the tool, read memory, hold state, or authenticate\n```\n\n- **CapabilityRegistry** — the catalog of stable capabilities (the 20 MCP tools map here).\n- **CapabilityResolver** — picks the implementation for this tenant/tier/context.\n- **AgentRegistry** — which agent persona/skill owns which capability.\n- **SpineCache (client)** — read-through helper; ADK hands the resolved ref down,\n  it does not fetch.\n\nBecause the ADK is pure and stateless, it can run before the Gateway on\nLLM-initiated calls (see §1). Resolution is hints; nothing is committed until the\nGateway authenticates and the request reaches MCP → Spine Cache.\n\n---\n\n## 5. Spine Cache — Build, Serve, Invalidate\n\nSpine Cache is the **only** thing an agent reads. It is prepared context, not the\nrecord of truth. If it is wiped, nothing is lost — it rebuilds from Main Memory.\n\n```\nBUILD (on demand or on write):\n  Main Memory (D1 + R2 + Vectorize; Supabase for promoted tenants)\n    → assemble Entity 360 (entity + relationships + signals + memory matches)\n    → seal into D1 edge (spine_vault, AES-256-GCM) + KV (hot) + Vectorize index\n    → ready to serve in <10ms\n\nSERVE:\n  MCP read → Spine Cache hit (KV first, D1 edge next, Vectorize for semantic)\n    → never falls through to Main Memory on the hot path\n\nINVALIDATE (on write path):\n  Pipeline writes entity → KV CACHE key evicted for that entity\n    → next read rebuilds that slice from Main Memory\n    → SIGNAL_CACHE updated if state changed\n\nEVICTION:\n  KV TTL 60–300s (hot). D1 edge is durable mirror. Safe to evict anytime.\n  Rebuild cost is bounded: one Entity 360 assembly per cold entity.\n```\n\n**Guarantee:** Spine Cache is always rebuildable and always behind MCP. No agent\never sees a cache miss as an error — it sees a slightly slower read.\n\n---\n\n## 6. The Governed Write Path (propose → govern → write)\n\nNo agent writes to Spine. Ever. The only writer is the Pipeline. Everything an\nagent \"wants to remember\" or \"wants to change\" is a **proposal** that must clear\ngovernance first.\n\n```\n1. PROPOSE      Agent calls memory.propose / emits a Tool MCP proposal.\n                → D1 proposals table (Triage Bot queue). Nothing is true yet.\n\n2. GOVERN       Triage Bot (CF Workflow) scores confidence:\n                   ≥ 0.85   auto-approve\n                   0.60–0.84 HITL — surfaced in L2, NOT in chat\n                   < 0.60   reject (with reason, no silent drop)\n\n3. WRITE        On approve → Pipeline writes:\n                   Main Memory: Supabase (truth) + R2 (raw) + D1 (metadata)\n                                + filesystem vault (.iw-memory dual-write)\n                   Spine Cache: rebuilt slice + MCP invalidation\n\n4. NO ARCHIVE   A write is either ACTIVE, or SUPERSEDES a prior entry (with\n                lineage), or is REJECTED (with reason). Nothing is hidden or\n                dumped. (Constitutional rule D-2026-06-05-013.)\n```\n\n**Wall 5 restated:** approval is the **U4 Decide** stage, surfaced on the\n**S2 Awareness** surface — never in S3 Twin chat. (S = system surface,\nU = human stage; see `docs/tech/CANONICAL_TAXONOMY.md`.) Chat is not an audit\ntrail. A proposal approved in conversation is not approved.\n\n---\n\n## 7. The 20 Tools (capability surface)\n\nGrouped by MCP channel. Names are the stable capability surface; the ADK binds\neach to a tenant-specific implementation.\n\n```\nMEMORY MCP\n  memory.search_org            semantic search over org memory\n  memory.read_org              read a specific org memory entry\n  memory.propose               propose a new/updated org memory entry (governed)\n  memory.read_conversational   read prior conversational turns\n  memory.write_conversational  append a conversational turn (low-stakes)\n  memory.read_personal         read personal patterns/preferences\n  memory.list_decisions        list governance decisions (lineage)\n\nSESSION MCP\n  session.get_context          assemble session context (continuity)\n  session.summarize            summarize a session into a durable note (proposes)\n  session.list_recent          recent sessions for this tenant/user\n\nTOOL MCP\n  spine.entity.get             read a single entity (Entity 360 slice)\n  spine.entity.search          find entities by trait/type/relationship\n  spine.relationship.list      graph relations for an entity\n  signal.list                  time-ordered signals for an entity/tenant\n  signal.get                   read a single signal\n  proposal.create              create an action proposal (governed)\n  proposal.status              check a proposal's governance state\n  book.list                    book-of-projects entries (read)\n  kb.search                    knowledge base semantic search\n  playbook.handoff             emit a PLAYBOOK (JSON) for local execution\n```\n\n> Count check: this list is the canonical 20. Keep it in sync with\n> `ARCHITECTURE_AND_DATA_FLOW.md` (MCP SERVER box) if tools are added or removed.\n\n---\n\n## 8. Failure Modes & Degradation\n\n```\nSPINE CACHE COLD/EVICTED   → rebuild from Main Memory. Slower read, never an error.\nMAIN MEMORY UNREACHABLE    → reads still served from Spine Cache (last good state).\n                             Writes queue; proposals hold in D1 until Supabase returns.\nGOVERNANCE BACKLOG         → proposals wait in queue. Nothing auto-commits below 0.85.\n                             No silent writes. The wall holds under load.\nMCP AUTH FAILURE           → request rejected at Gateway. ADK hints already discarded\n                             (zero I/O, nothing leaked).\nNANGO TOKEN EXPIRED        → connector-sync refreshes; write path pauses for that\n                             source only. Spine Cache serves last known entity state.\nMODEL/LLM DOWN OR SWAPPED  → model is a parameter. Twin falls back to another model;\n                             Spine Cache, MCP, and Memory are unaffected.\n```\n\n**Invariant under every failure:** an agent never reads stale-as-error, never\nwrites ungoverned, and never reaches a tool or Main Memory directly. The walls in\n§2 hold even when components are degraded.\n\n---\n\n_The LLM reads Spine Cache. The Pipeline writes Main Memory. Governance stands\nbetween them. The Bridge makes it feel like one mind._\n"}