[
  {
    "id": "01-system-context",
    "title": "Enterprise Generative Search — System Context",
    "layout": "context",
    "canvas": {
      "width": 1980
    },
    "colWidth": 340,
    "system": {
      "label": "Generative Search Platform",
      "sub": "grounded answers over 40 M documents"
    },
    "groups": [
      {
        "side": "left",
        "title": "People it serves",
        "nodes": [
          {
            "id": "kw",
            "label": "Knowledge Worker",
            "sub": "9,000 daily active",
            "kind": "actor",
            "rel": "asks",
            "dir": "in"
          },
          {
            "id": "analyst",
            "label": "Research Analyst",
            "sub": "400 seats",
            "kind": "actor",
            "rel": "multi-hop",
            "dir": "in"
          },
          {
            "id": "field",
            "label": "Field Engineer",
            "sub": "1,200 mobile",
            "kind": "actor",
            "rel": "photo, voice",
            "dir": "in"
          },
          {
            "id": "steward",
            "label": "Knowledge Steward",
            "sub": "85 content owners",
            "kind": "actor",
            "rel": "curates",
            "dir": "in"
          }
        ]
      },
      {
        "side": "top",
        "title": "Unstructured content sources",
        "nodes": [
          {
            "id": "conf",
            "label": "Confluence and Jira",
            "sub": "engineering knowledge",
            "kind": "external",
            "rel": "REST"
          },
          {
            "id": "m365",
            "label": "Microsoft 365",
            "sub": "SharePoint, Teams, OneDrive",
            "kind": "external",
            "rel": "delta"
          },
          {
            "id": "snow",
            "label": "ServiceNow Knowledge",
            "sub": "support articles",
            "kind": "external",
            "rel": "KB API"
          },
          {
            "id": "archive",
            "label": "Document Archive",
            "sub": "12 TB scanned PDF",
            "kind": "external",
            "rel": "nightly",
            "kind2": "batch"
          }
        ]
      },
      {
        "side": "right",
        "title": "Structured, external and downstream",
        "nodes": [
          {
            "id": "lake",
            "label": "Databricks Lakehouse",
            "sub": "governed Delta tables",
            "kind": "external",
            "rel": "SQL"
          },
          {
            "id": "apps",
            "label": "Downstream Applications",
            "sub": "CRM and intranet assistants",
            "kind": "external",
            "rel": "API",
            "dir": "in"
          },
          {
            "id": "reg",
            "label": "Regulator and Standards Feeds",
            "sub": "public web",
            "kind": "external",
            "rel": "crawl",
            "kind2": "batch"
          }
        ]
      },
      {
        "side": "bottom",
        "title": "Platform services it depends on",
        "nodes": [
          {
            "id": "entra",
            "label": "Microsoft Entra ID",
            "sub": "identity and groups",
            "kind": "security",
            "rel": "OIDC, OBO",
            "icon": "azure_AzureActiveDirectory__Identity"
          },
          {
            "id": "aoai",
            "label": "Azure AI Foundry",
            "sub": "Azure OpenAI models",
            "kind": "security",
            "rel": "inference"
          },
          {
            "id": "safety",
            "label": "Azure AI Content Safety",
            "sub": "Prompt Shields",
            "kind": "security",
            "rel": "screening"
          },
          {
            "id": "obs",
            "label": "Azure Monitor and Langfuse",
            "sub": "traces and telemetry",
            "kind": "security",
            "rel": "OTLP",
            "dir": "out",
            "kind2": "async"
          }
        ]
      }
    ],
    "note": "Read-only against every source. The platform indexes and cites content; it never edits or republishes it.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice",
      "date": "2026-09"
    }
  },
  {
    "id": "02-high-level-architecture",
    "title": "High-Level Architecture — Ask to Assured Answer",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "stages": [
      {
        "title": "Ask",
        "nodes": [
          {
            "id": "ui",
            "label": "Web and Mobile UI",
            "sub": "streamed answers",
            "icon": "net_mobile"
          },
          {
            "id": "api",
            "label": "Answer API",
            "sub": "OpenAPI, SSE",
            "kind": "integration",
            "icon": "fa5_plug"
          },
          {
            "id": "gw",
            "label": "Search Gateway",
            "sub": "FastAPI on AKS"
          }
        ]
      },
      {
        "title": "Understand",
        "nodes": [
          {
            "id": "qu",
            "label": "Query Understanding",
            "sub": "intent, entities, filters"
          },
          {
            "id": "ent",
            "label": "Entitlement Resolver",
            "sub": "Entra group set",
            "kind": "security",
            "icon": "fa5_user_shield"
          },
          {
            "id": "conv",
            "label": "Conversation State",
            "sub": "PostgreSQL",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Plan",
        "nodes": [
          {
            "id": "plan",
            "label": "Query Planner",
            "sub": "LangGraph"
          },
          {
            "id": "pol",
            "label": "Retrieval Policy",
            "sub": "per source and class",
            "kind": "security",
            "icon": "fa5_balance_scale"
          },
          {
            "id": "budget",
            "label": "Budget Governor",
            "sub": "tokens, hops, time",
            "kind": "decision",
            "icon": "fa5_coins"
          }
        ]
      },
      {
        "title": "Retrieve",
        "nodes": [
          {
            "id": "hybrid",
            "label": "Hybrid Index",
            "sub": "Azure AI Search",
            "kind": "store"
          },
          {
            "id": "struct",
            "label": "Structured Retrieval",
            "sub": "governed SQL views",
            "kind": "store"
          },
          {
            "id": "graph",
            "label": "Knowledge Graph",
            "sub": "Apache AGE",
            "kind": "store"
          },
          {
            "id": "cache",
            "label": "Answer Cache",
            "sub": "Redis, ACL-keyed",
            "kind": "store",
            "icon": "azure_cache-redis"
          }
        ]
      },
      {
        "title": "Rank",
        "nodes": [
          {
            "id": "fuse",
            "label": "Fusion",
            "sub": "reciprocal rank"
          },
          {
            "id": "rerank",
            "label": "Cross-Encoder Rerank",
            "sub": "bge-reranker-v2-m3"
          },
          {
            "id": "select",
            "label": "Evidence Selection",
            "sub": "diversity and authority",
            "icon": "fa5_check_double"
          }
        ]
      },
      {
        "title": "Generate",
        "nodes": [
          {
            "id": "ctx",
            "label": "Context Builder",
            "sub": "fenced, budgeted"
          },
          {
            "id": "mgw",
            "label": "Model Gateway",
            "sub": "LiteLLM proxy",
            "kind": "integration"
          },
          {
            "id": "synth",
            "label": "Synthesiser",
            "sub": "structured answer"
          }
        ]
      },
      {
        "title": "Assure",
        "nodes": [
          {
            "id": "ground",
            "label": "Grounding Verifier",
            "sub": "claim-level NLI"
          },
          {
            "id": "shield",
            "label": "Injection and Safety Filter",
            "sub": "Prompt Shields",
            "kind": "security"
          },
          {
            "id": "ans",
            "label": "Answer with Citations",
            "sub": "or search fallback"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "gw",
        "to": "cache",
        "label": "cache probe",
        "kind": "sync",
        "route": "gutter"
      },
      {
        "from": "ground",
        "to": "plan",
        "label": "replan",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "Ingestion is view 16. Identity, observability, evaluation and cost control are acts 6 and 7.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "03-the-evidence-contract",
    "title": "The Evidence Contract — The Three Rules Everything Else Follows From",
    "layout": "nested",
    "canvas": {
      "width": 1760
    },
    "boxes": [
      {
        "title": "Rule 1 — Nothing enters the context that the caller could not open themselves",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Enforced here",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Entitlement Resolver",
                "sub": "group set per request",
                "kind": "security",
                "icon": "fa5_user_shield"
              },
              {
                "label": "Index-side security filter",
                "sub": "never post-filtered",
                "kind": "security"
              },
              {
                "label": "ACL fingerprint in cache key",
                "sub": "SHA-256 of group set",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Therefore forbidden",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Model holding an index credential",
                "sub": "it requests, never queries",
                "kind": "risk"
              },
              {
                "label": "One answer cache for all callers",
                "sub": "cross-principal reuse",
                "kind": "risk"
              }
            ]
          }
        ]
      },
      {
        "title": "Rule 2 — Every sentence carries an evidence id the retriever minted, or it is not shown",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Enforced here",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Evidence ids minted at retrieval",
                "sub": "chunk plus version"
              },
              {
                "label": "Claim to evidence binding",
                "sub": "verified, not requested"
              },
              {
                "label": "Provenance persisted",
                "sub": "with every answer",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Therefore forbidden",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Model-written citations",
                "sub": "a string it can invent",
                "kind": "risk"
              },
              {
                "label": "Unbound sentence rendered",
                "sub": "dropped or flagged",
                "kind": "decision"
              }
            ]
          }
        ]
      },
      {
        "title": "Rule 3 — Retrieved content is data. Only the system prompt and the caller turn are instructions",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Enforced here",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Structural fencing",
                "sub": "evidence in a typed slot",
                "kind": "security"
              },
              {
                "label": "Injection screening",
                "sub": "at index and at query",
                "kind": "security"
              },
              {
                "label": "Tool broker with allowlist",
                "sub": "policy per query class",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Therefore forbidden",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Tool call sourced from a document",
                "sub": "never honoured",
                "kind": "risk"
              },
              {
                "label": "Free-form model egress",
                "sub": "no open network",
                "kind": "risk"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "label": "Consequence — the CRM assistant needed no access model of its own",
        "kind": "opportunity"
      },
      {
        "label": "Consequence — any answer replays and re-derives from its evidence ids",
        "kind": "opportunity"
      }
    ],
    "note": "The test of the contract: an answer that cannot be re-derived from its evidence ids is a defect, not a matter of style.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "04-query-classes-and-routing",
    "title": "Query Classes and the Routing Policy",
    "layout": "grid",
    "canvas": {
      "width": 1820
    },
    "laneHeaderWidth": 190,
    "columns": [
      "Recognised by",
      "Retrieval plan",
      "Generation mode",
      "Budget and target"
    ],
    "rows": [
      {
        "title": "Lookup",
        "cells": [
          [
            {
              "label": "Short, entity-bearing",
              "sub": "38% of traffic"
            }
          ],
          [
            {
              "label": "Hybrid, depth 30",
              "sub": "single pass",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Extractive answer",
              "sub": "one passage, quoted"
            }
          ],
          [
            {
              "label": "4k tokens, 2.5 s P95",
              "sub": "cacheable",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Explanatory",
        "cells": [
          [
            {
              "label": "How or why phrasing",
              "sub": "31% of traffic"
            }
          ],
          [
            {
              "label": "Hybrid, depth 80",
              "sub": "rewrite and expand",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Synthesis over 6-10 chunks",
              "sub": "claim-bound"
            }
          ],
          [
            {
              "label": "14k tokens, 6 s P95",
              "sub": "cacheable",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Multi-hop or comparative",
        "cells": [
          [
            {
              "label": "Several entities, contrast",
              "sub": "11% of traffic"
            }
          ],
          [
            {
              "label": "Decomposed sub-queries",
              "sub": "graph-assisted",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Agentic loop, 3 hops max",
              "sub": "contradiction check"
            }
          ],
          [
            {
              "label": "45k tokens, 18 s P95",
              "sub": "never cached",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Structured or numeric",
        "cells": [
          [
            {
              "label": "Aggregation verbs, metrics",
              "sub": "9% of traffic"
            }
          ],
          [
            {
              "label": "NL to SQL on allowlist",
              "sub": "semantic layer only",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Table plus narrative",
              "sub": "figures never restated"
            }
          ],
          [
            {
              "label": "8k tokens, 9 s P95",
              "sub": "result cached",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Multimodal",
        "cells": [
          [
            {
              "label": "Image or audio attached",
              "sub": "6% of traffic"
            }
          ],
          [
            {
              "label": "Cross-modal plus text",
              "sub": "figure and transcript",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Answer with a visual crop",
              "sub": "page-anchored"
            }
          ],
          [
            {
              "label": "20k tokens, 12 s P95",
              "sub": "never cached",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Ambiguous or uncovered",
        "cells": [
          [
            {
              "label": "Low retrieval confidence",
              "sub": "5% of traffic"
            }
          ],
          [
            {
              "label": "Broad recall probe",
              "sub": "then stop",
              "kind": "store"
            }
          ],
          [
            {
              "label": "No generation at all",
              "sub": "clarify or list results",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Under 1 s, no model cost",
              "sub": "the cheapest answer",
              "kind": "decision"
            }
          ]
        ]
      }
    ],
    "note": "The class is decided before any model is called, so the expensive path is a routing outcome rather than the default.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "05-actors-and-journeys",
    "title": "Actors and Their Core Journeys",
    "layout": "actors",
    "canvas": {
      "width": 1860
    },
    "cardWidth": 280,
    "groups": [
      {
        "title": "The people who ask",
        "kind": "boundary",
        "actors": [
          {
            "id": "kw",
            "label": "Knowledge Worker",
            "sub": "9,000 daily, 26 queries a week",
            "goal": "Give me an answer I can paste into a client mail without opening three documents to check it first.",
            "journeys": [
              {
                "id": "j-ask",
                "label": "Ask and act on one answer",
                "sub": "180k queries a month"
              },
              {
                "label": "Follow up in the same thread"
              },
              {
                "label": "Open the source that convinced me"
              }
            ]
          },
          {
            "id": "analyst",
            "label": "Research Analyst",
            "sub": "400 seats, regulated work",
            "goal": "Show me every place we said something about this, including the places that disagree, and let me cite it.",
            "journeys": [
              {
                "id": "j-research",
                "label": "Answer a multi-hop question",
                "sub": "9k a month"
              },
              {
                "label": "Compare positions across sources"
              },
              {
                "label": "Export an evidence pack"
              }
            ]
          },
          {
            "id": "field",
            "label": "Field Engineer",
            "sub": "1,200 mobile, low bandwidth",
            "goal": "Let me photograph the panel in front of me and get the right procedure for that exact revision.",
            "journeys": [
              {
                "label": "Search from a photo"
              },
              {
                "label": "Ask by voice, hands busy"
              },
              {
                "label": "Pin a procedure offline"
              }
            ]
          }
        ]
      },
      {
        "title": "The people who keep it honest",
        "kind": "boundary",
        "actors": [
          {
            "id": "steward",
            "label": "Knowledge Steward",
            "sub": "85 content owners",
            "goal": "Tell me why my document is not being found, in terms I can act on without raising a ticket.",
            "journeys": [
              {
                "id": "j-curate",
                "label": "Diagnose a document that never surfaces",
                "sub": "the trust journey"
              },
              {
                "label": "Retire and supersede content"
              },
              {
                "label": "Read my domain coverage report"
              }
            ]
          },
          {
            "id": "sre",
            "label": "Search Platform Engineer",
            "sub": "6 engineers, on call",
            "goal": "When an answer is wrong, tell me in one trace whether it was retrieval, ranking, context or the model.",
            "journeys": [
              {
                "label": "Triage a bad answer from its trace"
              },
              {
                "label": "Ship a retrieval change behind a gate"
              },
              {
                "label": "Rebuild an index without downtime"
              }
            ]
          },
          {
            "id": "ciso",
            "label": "Security and Compliance Officer",
            "sub": "2 named owners",
            "goal": "Prove to an auditor that no answer ever contained a passage its reader could not have opened.",
            "journeys": [
              {
                "label": "Replay an answer for an audit"
              },
              {
                "label": "Attest the entitlement path"
              },
              {
                "label": "Review injection and safety events"
              }
            ]
          }
        ]
      },
      {
        "title": "Machines that act without being asked",
        "kind": "cloud",
        "actors": [
          {
            "id": "conn",
            "label": "Source Connectors",
            "kind": "platform",
            "sub": "6 sources, delta-driven",
            "goal": "Notice every change in my source within its freshness class and never lose one silently.",
            "journeys": [
              {
                "label": "Pull a delta and enqueue it"
              },
              {
                "label": "Reconcile a missed change"
              }
            ]
          },
          {
            "id": "aclsync",
            "label": "Entitlement Sync",
            "kind": "platform",
            "sub": "60-second target",
            "goal": "Make a permission change true in the index before the person it affects asks their next question.",
            "journeys": [
              {
                "label": "Apply an ACL delta"
              },
              {
                "label": "Invalidate affected cache keys"
              }
            ],
            "icon": "fa5_user_shield"
          },
          {
            "id": "evalrun",
            "label": "Nightly Evaluation Run",
            "kind": "platform",
            "sub": "1,400 golden queries",
            "goal": "Fail the build before a regression reaches a person who is going to trust the answer.",
            "journeys": [
              {
                "label": "Score retrieval and generation"
              },
              {
                "label": "Block a release on a gate"
              }
            ]
          },
          {
            "id": "reindex",
            "label": "Re-embed and Compact",
            "kind": "platform",
            "sub": "model-version driven",
            "goal": "Move the corpus to a new embedding model without a day where the index answers from two.",
            "journeys": [
              {
                "label": "Shadow-build a new index"
              },
              {
                "label": "Cut over by alias"
              }
            ]
          }
        ]
      },
      {
        "title": "Systems that consume answers",
        "kind": "cloud",
        "actors": [
          {
            "id": "crm",
            "label": "CRM Assistant",
            "kind": "external",
            "sub": "on-behalf-of the seller",
            "goal": "Ask on my user's behalf and inherit exactly what they may see, with no access model of my own.",
            "journeys": [
              {
                "label": "Ask with a delegated token"
              },
              {
                "label": "Render citations inline"
              }
            ]
          },
          {
            "id": "widget",
            "label": "Intranet Answer Widget",
            "kind": "external",
            "sub": "read-only embed",
            "goal": "Answer the six questions people ask the intranet every day without a second content pipeline.",
            "journeys": [
              {
                "label": "Serve a cached common answer"
              },
              {
                "label": "Fall back to a result list"
              }
            ]
          }
        ]
      }
    ],
    "note": "Every actor here has a goal in their own words. Three of these journeys are mapped in views 06 to 08; the rest are served by views later in the set.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "06-journey-knowledge-worker",
    "title": "Journey — Ask a Question and Act on the Answer",
    "layout": "journey",
    "actor": {
      "label": "Knowledge Worker",
      "sub": "mid-task, in a hurry",
      "goal": "Get one answer good enough to act on without checking it myself",
      "trigger": "A client question they cannot answer from memory",
      "success": "They paste the answer and the link, and are still right a week later"
    },
    "phases": [
      {
        "title": "Notice",
        "sub": "in Teams or a doc"
      },
      {
        "title": "Ask"
      },
      {
        "title": "Wait",
        "moment": true
      },
      {
        "title": "Read and judge",
        "moment": true
      },
      {
        "title": "Act"
      }
    ],
    "lanes": [
      {
        "title": "What they do",
        "kind": "step",
        "cells": [
          [
            {
              "label": "Hits a gap mid-task"
            }
          ],
          [
            {
              "label": "Types one sentence"
            },
            {
              "label": "Adds no filters"
            }
          ],
          [
            {
              "label": "Watches the stream"
            }
          ],
          [
            {
              "label": "Skims the answer"
            },
            {
              "label": "Checks a citation"
            }
          ],
          [
            {
              "label": "Pastes it, or moves on"
            }
          ]
        ]
      },
      {
        "title": "Where",
        "kind": "touch",
        "cells": [
          [
            {
              "label": "Teams side panel"
            }
          ],
          [
            {
              "label": "Search box"
            }
          ],
          [
            {
              "label": "Streaming pane"
            }
          ],
          [
            {
              "label": "Answer with citations"
            }
          ],
          [
            {
              "label": "Their own document"
            }
          ]
        ]
      },
      {
        "title": "Behind the glass",
        "kind": "system",
        "cells": [
          [
            {
              "label": "Nothing yet"
            }
          ],
          [
            {
              "label": "Query understanding"
            },
            {
              "label": "Entitlement resolve"
            }
          ],
          [
            {
              "label": "Hybrid retrieve, rerank"
            },
            {
              "label": "First token at 1.2 s"
            }
          ],
          [
            {
              "label": "Claim-level binding"
            },
            {
              "label": "Source preview"
            }
          ],
          [
            {
              "label": "Feedback captured"
            }
          ]
        ]
      },
      {
        "title": "How it feels",
        "kind": "emotion",
        "levels": [
          "Confident",
          "Fine",
          "Doubtful"
        ],
        "points": [
          1,
          2,
          1,
          0,
          1
        ]
      },
      {
        "title": "Where it hurts",
        "kind": "pain",
        "cells": [
          [],
          [
            {
              "label": "Does not know what is indexed"
            }
          ],
          [
            {
              "label": "Blank pane reads as broken"
            }
          ],
          [
            {
              "label": "Confident answer, retired policy"
            },
            {
              "label": "No way to tell how sure it is"
            }
          ],
          [
            {
              "label": "Re-checks it anyway"
            }
          ]
        ]
      },
      {
        "title": "What answers it",
        "kind": "gain",
        "cells": [
          [],
          [
            {
              "label": "Scope chips from the plan"
            }
          ],
          [
            {
              "label": "Retrieval shown while waiting"
            }
          ],
          [
            {
              "label": "Version and as-of on each cite"
            },
            {
              "label": "Abstain when unsupported"
            }
          ],
          [
            {
              "label": "One-click open at the passage"
            }
          ]
        ]
      }
    ],
    "chain": true,
    "note": "The trough is not latency. It is that a fluent answer and a wrong answer look identical, which is why views 19, 21 and 26 exist.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "07-journey-research-analyst",
    "title": "Journey — Answering a Multi-Hop Question That Has to Survive Review",
    "layout": "journey",
    "actor": {
      "label": "Research Analyst",
      "sub": "regulated deliverable, named reviewer",
      "goal": "Assemble a defensible position from sources that do not agree with each other",
      "trigger": "A regulatory change, or a question from counsel",
      "success": "A reviewer accepts the evidence pack without re-doing the search"
    },
    "phases": [
      {
        "title": "Frame"
      },
      {
        "title": "Decompose"
      },
      {
        "title": "Gather"
      },
      {
        "title": "Reconcile",
        "moment": true
      },
      {
        "title": "Cite",
        "moment": true
      },
      {
        "title": "Deliver"
      }
    ],
    "lanes": [
      {
        "title": "What they do",
        "kind": "step",
        "cells": [
          [
            {
              "label": "States the real question"
            }
          ],
          [
            {
              "label": "Accepts or edits the plan"
            }
          ],
          [
            {
              "label": "Scans evidence, adds a source"
            }
          ],
          [
            {
              "label": "Weighs conflicting passages"
            }
          ],
          [
            {
              "label": "Checks every citation"
            }
          ],
          [
            {
              "label": "Exports the pack"
            }
          ]
        ]
      },
      {
        "title": "Where",
        "kind": "touch",
        "cells": [
          [
            {
              "label": "Research workspace"
            }
          ],
          [
            {
              "label": "Visible query plan"
            }
          ],
          [
            {
              "label": "Evidence tray"
            }
          ],
          [
            {
              "label": "Comparison table"
            }
          ],
          [
            {
              "label": "Citation panel"
            }
          ],
          [
            {
              "label": "Signed export"
            }
          ]
        ]
      },
      {
        "title": "Behind the glass",
        "kind": "system",
        "cells": [
          [
            {
              "label": "Intent and scope model"
            }
          ],
          [
            {
              "label": "Planner, 3 sub-queries"
            },
            {
              "label": "Graph expansion"
            }
          ],
          [
            {
              "label": "Per-hop retrieval"
            },
            {
              "label": "Diversity selection"
            }
          ],
          [
            {
              "label": "Contradiction detector"
            },
            {
              "label": "Authority and recency"
            }
          ],
          [
            {
              "label": "Claim to evidence binding"
            }
          ],
          [
            {
              "label": "Provenance record persisted"
            }
          ]
        ]
      },
      {
        "title": "How it feels",
        "kind": "emotion",
        "levels": [
          "In control",
          "Working",
          "Losing trust"
        ],
        "points": [
          2,
          2,
          1,
          0,
          1,
          2
        ]
      },
      {
        "title": "Where it hurts",
        "kind": "pain",
        "cells": [
          [],
          [
            {
              "label": "Plan is invisible, cannot steer"
            }
          ],
          [
            {
              "label": "Six near-identical passages"
            }
          ],
          [
            {
              "label": "Draft averaged two positions"
            },
            {
              "label": "False consensus reads as fact"
            }
          ],
          [
            {
              "label": "Citation points at the document"
            }
          ],
          []
        ]
      },
      {
        "title": "What answers it",
        "kind": "gain",
        "cells": [
          [],
          [
            {
              "label": "Editable plan before it runs"
            }
          ],
          [
            {
              "label": "Redundancy collapsed by MMR"
            }
          ],
          [
            {
              "label": "Disagreement is a stated state"
            },
            {
              "label": "Both positions kept, dated"
            }
          ],
          [
            {
              "label": "Cite anchors to the passage"
            }
          ],
          [
            {
              "label": "Pack replays from evidence ids"
            }
          ]
        ]
      }
    ],
    "chain": true,
    "note": "An averaged answer is worse than no answer here. Reconciliation is a first-class output, which is why contradiction is detected rather than smoothed.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "08-journey-knowledge-steward",
    "title": "Journey — Finding Out Why a Document Never Surfaces",
    "layout": "journey",
    "actor": {
      "label": "Knowledge Steward",
      "sub": "owns a domain, not the platform",
      "goal": "Make my domain answerable, and know when it is not",
      "trigger": "A colleague says the platform never finds our standard",
      "success": "The document is retrievable, and the steward knows why it was not"
    },
    "phases": [
      {
        "title": "Publish"
      },
      {
        "title": "Assume it works"
      },
      {
        "title": "Hear a complaint",
        "moment": true
      },
      {
        "title": "Diagnose",
        "moment": true
      },
      {
        "title": "Fix"
      },
      {
        "title": "Verify"
      }
    ],
    "lanes": [
      {
        "title": "What they do",
        "kind": "step",
        "cells": [
          [
            {
              "label": "Publishes to SharePoint"
            }
          ],
          [
            {
              "label": "Moves on"
            }
          ],
          [
            {
              "label": "Tries the query themselves"
            }
          ],
          [
            {
              "label": "Opens the document report"
            }
          ],
          [
            {
              "label": "Fixes title and metadata"
            },
            {
              "label": "Supersedes the old version"
            }
          ],
          [
            {
              "label": "Re-runs the probe query"
            }
          ]
        ]
      },
      {
        "title": "Where",
        "kind": "touch",
        "cells": [
          [
            {
              "label": "SharePoint library"
            }
          ],
          [
            {
              "label": "Nowhere"
            }
          ],
          [
            {
              "label": "The search box"
            }
          ],
          [
            {
              "label": "Steward console"
            }
          ],
          [
            {
              "label": "Source system"
            }
          ],
          [
            {
              "label": "Coverage report"
            }
          ]
        ]
      },
      {
        "title": "Behind the glass",
        "kind": "system",
        "cells": [
          [
            {
              "label": "Graph delta notices it"
            }
          ],
          [
            {
              "label": "Parse, chunk, embed, index"
            }
          ],
          [
            {
              "label": "Retrieval returns rivals"
            }
          ],
          [
            {
              "label": "Per-document diagnostics"
            },
            {
              "label": "Retrieval explain probe"
            }
          ],
          [
            {
              "label": "Incremental re-index"
            }
          ],
          [
            {
              "label": "Coverage metric recomputed"
            }
          ]
        ]
      },
      {
        "title": "How it feels",
        "kind": "emotion",
        "levels": [
          "Trusted",
          "Neutral",
          "Powerless"
        ],
        "points": [
          2,
          1,
          0,
          0,
          1,
          2
        ]
      },
      {
        "title": "Where it hurts",
        "kind": "pain",
        "cells": [
          [],
          [
            {
              "label": "No signal it was indexed"
            }
          ],
          [
            {
              "label": "Blamed for a platform fault"
            }
          ],
          [
            {
              "label": "Scanned PDF, no text layer"
            },
            {
              "label": "Nothing tells them that"
            }
          ],
          [],
          []
        ]
      },
      {
        "title": "What answers it",
        "kind": "gain",
        "cells": [
          [],
          [
            {
              "label": "Indexed receipt per document"
            }
          ],
          [
            {
              "label": "Self-service probe query"
            }
          ],
          [
            {
              "label": "Parse, chunk, ACL and OCR state"
            },
            {
              "label": "Named cause, not a ticket"
            }
          ],
          [
            {
              "label": "OCR path re-queued on demand"
            }
          ],
          [
            {
              "label": "Domain coverage trend"
            }
          ]
        ]
      }
    ],
    "chain": true,
    "note": "A steward with no diagnostics blames the platform, and the platform blames the content. The diagnostics in view 34 exist to end that argument.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "09-layered-architecture",
    "title": "Layered Architecture — What Depends on What",
    "layout": "bands",
    "canvas": {
      "width": 1820
    },
    "layerHeaderWidth": 170,
    "bands": [
      {
        "name": "Experience",
        "nodes": [
          {
            "id": "web",
            "label": "Web Search UI",
            "sub": "streamed, citation-first"
          },
          {
            "id": "teams",
            "label": "Teams App",
            "sub": "side panel"
          },
          {
            "id": "mob",
            "label": "Mobile Client",
            "sub": "photo and voice",
            "icon": "net_mobile"
          },
          {
            "id": "ansapi",
            "label": "Answer API",
            "sub": "SSE, OpenAPI",
            "kind": "integration",
            "icon": "fa5_plug"
          },
          {
            "id": "srchapi",
            "label": "Classic Search API",
            "sub": "the fallback surface",
            "kind": "integration",
            "icon": "fa5_search"
          }
        ]
      },
      {
        "name": "Answer orchestration",
        "nodes": [
          {
            "id": "qund",
            "label": "Query Understanding",
            "sub": "intent, entities, scope"
          },
          {
            "id": "plnr",
            "label": "Query Planner",
            "sub": "LangGraph state machine"
          },
          {
            "id": "loop",
            "label": "Agentic Controller",
            "sub": "3 hops, hard budget"
          },
          {
            "id": "asm",
            "label": "Answer Assembler",
            "sub": "claims and citations",
            "icon": "fa5_puzzle_piece"
          },
          {
            "id": "gov",
            "label": "Budget Governor",
            "sub": "tokens, time, hops",
            "kind": "decision",
            "icon": "fa5_coins"
          }
        ]
      },
      {
        "name": "Retrieval and ranking",
        "nodes": [
          {
            "id": "rfac",
            "label": "Retriever Facade",
            "sub": "one contract, four backends",
            "icon": "fa5_random"
          },
          {
            "id": "lex",
            "label": "Lexical Retriever",
            "sub": "BM25 and filters"
          },
          {
            "id": "vec",
            "label": "Vector Retriever",
            "sub": "HNSW, BGE-M3"
          },
          {
            "id": "sqlr",
            "label": "Structured Retriever",
            "sub": "governed SQL only"
          },
          {
            "id": "grf",
            "label": "Graph Retriever",
            "sub": "entity and supersession"
          },
          {
            "id": "rank",
            "label": "Fusion and Rerank",
            "sub": "RRF, cross-encoder"
          }
        ]
      },
      {
        "name": "Grounding and assurance",
        "nodes": [
          {
            "id": "bind",
            "label": "Claim Binder",
            "sub": "sentence to evidence id",
            "icon": "fa5_link"
          },
          {
            "id": "grd",
            "label": "Groundedness Verifier",
            "sub": "NLI over evidence",
            "icon": "fa5_check_double"
          },
          {
            "id": "contr",
            "label": "Contradiction Detector",
            "sub": "pairwise on claims",
            "icon": "fa5_not_equal"
          },
          {
            "id": "safe",
            "label": "Safety and Injection Filter",
            "sub": "Prompt Shields",
            "kind": "security"
          },
          {
            "id": "opa",
            "label": "Policy Engine",
            "sub": "OPA, source and tool rules",
            "kind": "security"
          }
        ]
      },
      {
        "name": "Model and tools",
        "nodes": [
          {
            "id": "mgw",
            "label": "Model Gateway",
            "sub": "LiteLLM, routing and budgets",
            "kind": "integration"
          },
          {
            "id": "llm",
            "label": "LLM Pool",
            "sub": "Azure OpenAI and vLLM"
          },
          {
            "id": "emb",
            "label": "Embedding Service",
            "sub": "TEI on GPU"
          },
          {
            "id": "rrk",
            "label": "Rerank Service",
            "sub": "TEI cross-encoder"
          },
          {
            "id": "tools",
            "label": "Tool Broker",
            "sub": "allowlisted, audited",
            "kind": "integration",
            "icon": "fa5_toolbox"
          }
        ]
      },
      {
        "name": "Knowledge platform",
        "nodes": [
          {
            "id": "conn",
            "label": "Connectors",
            "sub": "delta and CDC"
          },
          {
            "id": "parse",
            "label": "Parsing and OCR",
            "sub": "Tika, Document Intelligence"
          },
          {
            "id": "enrich",
            "label": "Enrichment",
            "sub": "entities, taxonomy, PII"
          },
          {
            "id": "chunk",
            "label": "Chunking",
            "sub": "per content type"
          },
          {
            "id": "embp",
            "label": "Embedding Pipeline",
            "sub": "batch, versioned"
          },
          {
            "id": "idx",
            "label": "Indexer",
            "sub": "idempotent upsert",
            "icon": "fa5_file_import"
          }
        ]
      },
      {
        "name": "Data and index",
        "nodes": [
          {
            "id": "hyb",
            "label": "Hybrid Index",
            "sub": "Azure AI Search",
            "kind": "store"
          },
          {
            "id": "age",
            "label": "Knowledge Graph",
            "sub": "PostgreSQL and AGE",
            "kind": "store"
          },
          {
            "id": "meta",
            "label": "Metadata and Provenance",
            "sub": "PostgreSQL",
            "kind": "store"
          },
          {
            "id": "lake2",
            "label": "Content Lake",
            "sub": "ADLS Gen2 and Delta",
            "kind": "store"
          },
          {
            "id": "red",
            "label": "Cache",
            "sub": "Azure Cache for Redis",
            "kind": "store",
            "icon": "azure_cache-redis"
          },
          {
            "id": "trc",
            "label": "Trace Store",
            "sub": "Langfuse on PostgreSQL",
            "kind": "store"
          }
        ]
      },
      {
        "name": "Platform and control",
        "nodes": [
          {
            "id": "idp",
            "label": "Entra ID and Key Vault",
            "sub": "identity and secrets",
            "kind": "security",
            "icon": "azure_AzureKeyVault__Security"
          },
          {
            "id": "aks",
            "label": "AKS and Terraform",
            "sub": "CPU and GPU pools",
            "kind": "platform"
          },
          {
            "id": "otel",
            "label": "OpenTelemetry",
            "sub": "one trace per request",
            "kind": "platform"
          },
          {
            "id": "evalh",
            "label": "Evaluation Harness",
            "sub": "Ragas and IR metrics",
            "kind": "platform"
          },
          {
            "id": "fin",
            "label": "Cost Control",
            "sub": "per-query accounting",
            "kind": "platform"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "ansapi",
        "to": "plnr",
        "label": "one entry point"
      },
      {
        "from": "plnr",
        "to": "rfac",
        "label": "retrieval requests"
      },
      {
        "from": "rfac",
        "to": "hyb",
        "label": "filtered query"
      },
      {
        "from": "mgw",
        "to": "llm",
        "label": "routed call"
      },
      {
        "from": "idx",
        "to": "hyb",
        "label": "upsert",
        "kind": "batch"
      },
      {
        "from": "grd",
        "to": "plnr",
        "label": "replan",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "Dependencies point down. The single upward call is the verifier asking the planner to retrieve again; it is bounded by the budget governor and is drawn rather than hidden.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "10-container-architecture",
    "title": "Container Architecture — The Deployable Units",
    "layout": "nested",
    "canvas": {
      "width": 1840
    },
    "boxes": [
      {
        "title": "Azure landing zone — AKS, private networking only",
        "kind": "cloud",
        "dir": "col",
        "children": [
          {
            "title": "Answer plane (namespace: answer)",
            "kind": "boundary",
            "nodes": [
              {
                "id": "gw",
                "label": "Search Gateway",
                "sub": "FastAPI, SSE, 12 pods"
              },
              {
                "id": "qu",
                "label": "Query Understanding",
                "sub": "Python, 6 pods"
              },
              {
                "id": "pl",
                "label": "Planner and Controller",
                "sub": "LangGraph, 8 pods"
              },
              {
                "id": "as",
                "label": "Answer Assembler",
                "sub": "Python, 8 pods",
                "icon": "fa5_puzzle_piece"
              },
              {
                "id": "vf",
                "label": "Verifier",
                "sub": "NLI, 4 GPU pods",
                "icon": "fa5_check_double"
              }
            ]
          },
          {
            "title": "Retrieval plane (namespace: retrieve)",
            "kind": "boundary",
            "nodes": [
              {
                "id": "rf",
                "label": "Retriever Facade",
                "sub": "Python, 10 pods",
                "icon": "fa5_random"
              },
              {
                "id": "sr",
                "label": "Structured Retriever",
                "sub": "SQL guard, 4 pods"
              },
              {
                "id": "gr",
                "label": "Graph Retriever",
                "sub": "openCypher, 4 pods"
              },
              {
                "id": "es",
                "label": "Embed Service",
                "sub": "TEI, 6 GPU pods"
              },
              {
                "id": "rs",
                "label": "Rerank Service",
                "sub": "TEI, 6 GPU pods"
              }
            ]
          },
          {
            "title": "Knowledge plane (namespace: ingest)",
            "kind": "boundary",
            "nodes": [
              {
                "id": "af",
                "label": "Airflow",
                "sub": "KubernetesExecutor",
                "icon": "airflow"
              },
              {
                "id": "cw",
                "label": "Connector Workers",
                "sub": "one per source"
              },
              {
                "id": "pw",
                "label": "Parse and OCR Workers",
                "sub": "Tika, autoscaled"
              },
              {
                "id": "ew",
                "label": "Chunk and Embed Workers",
                "sub": "batch GPU"
              },
              {
                "id": "ix",
                "label": "Indexer",
                "sub": "idempotent upsert",
                "icon": "fa5_file_import"
              }
            ]
          },
          {
            "title": "Shared control services (namespace: platform)",
            "kind": "boundary",
            "nodes": [
              {
                "id": "mg",
                "label": "Model Gateway",
                "sub": "LiteLLM, 6 pods",
                "kind": "integration"
              },
              {
                "id": "tb",
                "label": "Tool Broker",
                "sub": "allowlist, 4 pods",
                "kind": "integration",
                "icon": "fa5_toolbox"
              },
              {
                "id": "pe",
                "label": "Policy Engine",
                "sub": "OPA sidecar",
                "kind": "security"
              },
              {
                "id": "lf",
                "label": "Langfuse",
                "sub": "self-hosted traces",
                "kind": "platform"
              },
              {
                "id": "fl",
                "label": "flagd",
                "sub": "retrieval flags",
                "kind": "platform"
              }
            ]
          }
        ]
      },
      {
        "title": "Managed data services — private endpoints",
        "kind": "cloud",
        "dir": "row",
        "children": [
          {
            "title": "Retrieval stores",
            "kind": "boundary",
            "nodes": [
              {
                "id": "ais",
                "label": "Azure AI Search",
                "sub": "S3, 12 partitions",
                "kind": "store",
                "icon": "azure_search"
              },
              {
                "id": "pg",
                "label": "PostgreSQL Flexible",
                "sub": "metadata and AGE graph",
                "kind": "store"
              },
              {
                "id": "rd",
                "label": "Azure Cache for Redis",
                "sub": "answer and embedding cache",
                "kind": "store",
                "icon": "azure_cache-redis"
              }
            ]
          },
          {
            "title": "Content and events",
            "kind": "boundary",
            "nodes": [
              {
                "id": "adls",
                "label": "ADLS Gen2",
                "sub": "raw and rendered, 12 TB",
                "kind": "store"
              },
              {
                "id": "eh",
                "label": "Event Hubs",
                "sub": "change and telemetry",
                "kind": "queue"
              },
              {
                "id": "sb",
                "label": "Service Bus",
                "sub": "ingestion work queues",
                "kind": "queue"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "id": "aoai",
        "label": "Azure OpenAI",
        "sub": "synthesis models",
        "kind": "external",
        "icon": "azure_openai"
      },
      {
        "id": "docint",
        "label": "Document Intelligence",
        "sub": "layout OCR",
        "kind": "external"
      },
      {
        "id": "acs",
        "label": "Content Safety",
        "sub": "Prompt Shields",
        "kind": "external"
      },
      {
        "id": "dbx",
        "label": "Databricks SQL",
        "sub": "governed tables",
        "kind": "external"
      },
      {
        "id": "aad",
        "label": "Microsoft Entra ID",
        "sub": "OBO and groups",
        "kind": "external",
        "icon": "azure_AzureActiveDirectory__Identity"
      }
    ],
    "edges": [
      {
        "from": "gw",
        "to": "pl",
        "label": "plan"
      },
      {
        "from": "pl",
        "to": "rf",
        "label": "retrieve"
      },
      {
        "from": "rf",
        "to": "ais",
        "label": "hybrid query"
      },
      {
        "from": "sr",
        "to": "dbx",
        "label": "allowlisted SQL"
      },
      {
        "from": "mg",
        "to": "aoai",
        "label": "routed inference",
        "route": "gutter"
      },
      {
        "from": "ix",
        "to": "ais",
        "label": "upsert",
        "kind": "batch"
      },
      {
        "from": "cw",
        "to": "sb",
        "label": "work items",
        "kind": "async"
      }
    ],
    "note": "GPU pods carry the embedding, reranking and verification models. No pod holds a source credential; connectors use workload identity against Key Vault.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "11-query-understanding",
    "title": "Query Understanding — From a Sentence to an Executable Plan",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1800
    },
    "stages": [
      {
        "title": "Receive",
        "nodes": [
          {
            "id": "raw",
            "label": "Raw ask",
            "sub": "text, voice or image"
          },
          {
            "id": "lang",
            "label": "Language detect",
            "sub": "fastText, 14 languages"
          },
          {
            "id": "scrub",
            "label": "PII scrub on the query",
            "sub": "Presidio",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Interpret",
        "nodes": [
          {
            "id": "cls",
            "label": "Class and intent",
            "sub": "6 classes, view 04",
            "kind": "decision"
          },
          {
            "id": "ner",
            "label": "Entities and filters",
            "sub": "product, date, org"
          },
          {
            "id": "time",
            "label": "Temporal scope",
            "sub": "as-of resolution",
            "icon": "fa5_clock"
          }
        ]
      },
      {
        "title": "Contextualise",
        "nodes": [
          {
            "id": "coref",
            "label": "Coreference resolve",
            "sub": "from turn history"
          },
          {
            "id": "state",
            "label": "Conversation state",
            "sub": "PostgreSQL, 30 turns",
            "kind": "store"
          },
          {
            "id": "scope",
            "label": "Scope chips",
            "sub": "shown to the user"
          }
        ]
      },
      {
        "title": "Authorise",
        "nodes": [
          {
            "id": "obo",
            "label": "On-behalf-of token",
            "sub": "Entra OBO",
            "kind": "security"
          },
          {
            "id": "grp",
            "label": "Group set expansion",
            "sub": "cached 60 s",
            "kind": "security"
          },
          {
            "id": "fp",
            "label": "ACL fingerprint",
            "sub": "SHA-256, cache key",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Rewrite",
        "nodes": [
          {
            "id": "rw",
            "label": "Query rewrite",
            "sub": "Qwen3-8B on vLLM"
          },
          {
            "id": "mq",
            "label": "Multi-query expansion",
            "sub": "up to 4 variants"
          },
          {
            "id": "syn",
            "label": "Domain synonyms",
            "sub": "curated, not learned"
          }
        ]
      },
      {
        "title": "Emit",
        "nodes": [
          {
            "id": "qp",
            "label": "QueryPlan object",
            "sub": "typed, logged, replayable"
          },
          {
            "id": "cachek",
            "label": "Cache probe",
            "sub": "exact then semantic",
            "kind": "store",
            "icon": "azure_cache-redis"
          },
          {
            "id": "fallb",
            "label": "Low confidence exit",
            "sub": "clarify or list",
            "kind": "risk"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "cls",
        "to": "fallb",
        "label": "confidence below 0.45",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "Authorisation is resolved here, before any retrieval, because the group set is an input to both the query filter and the cache key.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "12-retrieval-fabric",
    "title": "Retrieval Fabric — Four Backends, One Contract",
    "layout": "nested",
    "canvas": {
      "width": 1840
    },
    "boxes": [
      {
        "title": "The contract every backend honours",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Inputs it must accept",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Principal group set",
                "sub": "mandatory, never optional",
                "kind": "security"
              },
              {
                "label": "Classification ceiling",
                "sub": "per request",
                "kind": "security"
              },
              {
                "label": "Freshness and as-of",
                "sub": "declared, not implied"
              }
            ]
          },
          {
            "title": "Outputs it must return",
            "kind": "boundary",
            "nodes": [
              {
                "label": "Evidence id",
                "sub": "chunk plus version"
              },
              {
                "label": "Score and its scale",
                "sub": "comparable after fusion"
              },
              {
                "label": "Retrieval reason",
                "sub": "why this was returned"
              }
            ]
          }
        ]
      },
      {
        "title": "Candidate generation",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Lexical",
            "kind": "plain",
            "nodes": [
              {
                "label": "BM25 over Azure AI Search",
                "sub": "field-boosted",
                "kind": "store"
              },
              {
                "label": "Analyzer and synonym map",
                "sub": "curated per domain"
              },
              {
                "label": "Exact identifier match",
                "sub": "part and policy numbers"
              }
            ]
          },
          {
            "title": "Semantic",
            "kind": "plain",
            "nodes": [
              {
                "label": "Dense HNSW",
                "sub": "BGE-M3, 1024-d",
                "kind": "store"
              },
              {
                "label": "Learned sparse terms",
                "sub": "same model, lexical bridge",
                "kind": "store"
              },
              {
                "label": "Multimodal vectors",
                "sub": "figures and frames",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Structured",
            "kind": "plain",
            "nodes": [
              {
                "label": "Semantic SQL views",
                "sub": "allowlisted only",
                "kind": "store"
              },
              {
                "label": "NL to SQL guard",
                "sub": "parse, bound, explain",
                "kind": "security"
              },
              {
                "label": "Row to evidence adapter",
                "sub": "figures become citable"
              }
            ]
          },
          {
            "title": "Graph",
            "kind": "plain",
            "nodes": [
              {
                "label": "Entity and relation store",
                "sub": "Apache AGE on PostgreSQL",
                "kind": "store"
              },
              {
                "label": "Supersession edges",
                "sub": "replaces and replaced-by"
              },
              {
                "label": "Hop expansion",
                "sub": "2 hops, capped fan-out"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "label": "Retrieval cache",
        "sub": "Redis, ACL-fingerprinted",
        "kind": "store",
        "icon": "azure_cache-redis"
      },
      {
        "label": "Per-source ranking policy",
        "sub": "authority and recency weights"
      },
      {
        "label": "Retrieval trace",
        "sub": "every backend call recorded",
        "kind": "platform"
      }
    ],
    "note": "Adding a fifth backend means implementing the contract, not changing the planner. That is the whole reason the facade exists.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "13-integration-surface",
    "title": "Integration Surface — Every Way This Platform Touches Another System",
    "layout": "hub",
    "canvas": {
      "width": 1800
    },
    "left": {
      "title": "Consumers",
      "nodes": [
        {
          "id": "cweb",
          "label": "Web and Teams UI",
          "rel": "SSE"
        },
        {
          "id": "cmob",
          "label": "Mobile Client",
          "rel": "REST",
          "icon": "net_mobile"
        },
        {
          "id": "ccrm",
          "label": "CRM Assistant",
          "kind": "external",
          "rel": "OBO token"
        },
        {
          "id": "cwid",
          "label": "Intranet Widget",
          "kind": "external",
          "rel": "embed"
        }
      ]
    },
    "centre": {
      "title": "Published interfaces",
      "nodes": [
        {
          "id": "ianswer",
          "label": "Answer API",
          "sub": "POST /v1/answer, SSE",
          "kind": "integration",
          "icon": "fa5_plug"
        },
        {
          "id": "isearch",
          "label": "Search API",
          "sub": "GET /v1/search, ranked list",
          "kind": "integration",
          "icon": "fa5_search"
        },
        {
          "id": "iadmin",
          "label": "Admin and Steward API",
          "sub": "diagnostics, coverage",
          "kind": "integration",
          "icon": "fa5_user_cog"
        },
        {
          "id": "iingest",
          "label": "Ingestion API",
          "sub": "push for systems without a delta feed",
          "kind": "integration",
          "icon": "fa5_file_import"
        }
      ]
    },
    "right": {
      "title": "Dependencies",
      "nodes": [
        {
          "id": "dsrc",
          "label": "Content Source Systems",
          "sub": "Graph, Confluence, ServiceNow",
          "kind": "external",
          "rel": "delta",
          "dir": "out",
          "icon": "fa5_folder_open"
        },
        {
          "id": "ddbx",
          "label": "Databricks SQL",
          "kind": "external",
          "rel": "SQL",
          "dir": "out"
        },
        {
          "id": "dai",
          "label": "Azure AI Services",
          "sub": "OpenAI, Safety, OCR",
          "kind": "external",
          "rel": "inference",
          "dir": "out",
          "icon": "azure_cognitive-services"
        },
        {
          "id": "dentra",
          "label": "Microsoft Entra ID",
          "kind": "security",
          "rel": "OIDC",
          "dir": "out",
          "icon": "azure_AzureActiveDirectory__Identity"
        }
      ]
    },
    "note": "Four interfaces are published and versioned; everything else is an internal call. The six content sources are one box here because view 14 carries them one by one.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "14-source-connector-matrix",
    "title": "Source Connector Matrix — How Each Source Is Read, Authorised and Refreshed",
    "layout": "grid",
    "canvas": {
      "width": 1860
    },
    "laneHeaderWidth": 200,
    "columns": [
      "Change detection",
      "Authorisation model",
      "Freshness class",
      "Parse path"
    ],
    "rows": [
      {
        "title": "Microsoft 365",
        "cells": [
          [
            {
              "label": "Graph delta query",
              "sub": "8.1 M items"
            }
          ],
          [
            {
              "label": "Item ACL to Entra groups",
              "sub": "expanded at index",
              "kind": "security"
            }
          ],
          [
            {
              "label": "5 minutes P95",
              "sub": "collaboration class"
            }
          ],
          [
            {
              "label": "Native text plus Tika",
              "sub": "OCR only when scanned"
            }
          ]
        ]
      },
      {
        "title": "Confluence and Jira",
        "cells": [
          [
            {
              "label": "CQL updated-since",
              "sub": "1.4 M pages"
            }
          ],
          [
            {
              "label": "Space and page restrictions",
              "sub": "mapped to groups",
              "kind": "security"
            }
          ],
          [
            {
              "label": "15 minutes",
              "sub": "collaboration class"
            }
          ],
          [
            {
              "label": "Storage-format HTML",
              "sub": "macro-aware"
            }
          ]
        ]
      },
      {
        "title": "ServiceNow Knowledge",
        "cells": [
          [
            {
              "label": "sys_updated_on poll",
              "sub": "220 k articles"
            }
          ],
          [
            {
              "label": "User criteria to groups",
              "sub": "role-derived",
              "kind": "security"
            }
          ],
          [
            {
              "label": "15 minutes",
              "sub": "support class"
            }
          ],
          [
            {
              "label": "HTML plus attachments",
              "sub": "article as one unit"
            }
          ]
        ]
      },
      {
        "title": "Document archive",
        "cells": [
          [
            {
              "label": "Blob change feed",
              "sub": "26 M scanned pages"
            }
          ],
          [
            {
              "label": "Folder ACL, inherited",
              "sub": "coarse by design",
              "kind": "security"
            }
          ],
          [
            {
              "label": "24 hours",
              "sub": "archive class"
            }
          ],
          [
            {
              "label": "Document Intelligence",
              "sub": "layout and tables"
            }
          ]
        ]
      },
      {
        "title": "Databricks governed tables",
        "cells": [
          [
            {
              "label": "Not indexed at all",
              "sub": "queried live",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Unity Catalog grants",
              "sub": "caller passed through",
              "kind": "security"
            }
          ],
          [
            {
              "label": "Query time",
              "sub": "no staleness"
            }
          ],
          [
            {
              "label": "No parse, rows are evidence",
              "sub": "adapter, not chunker"
            }
          ]
        ]
      },
      {
        "title": "Public web and regulators",
        "cells": [
          [
            {
              "label": "Sitemap and ETag crawl",
              "sub": "40 domains"
            }
          ],
          [
            {
              "label": "Public, tenant-wide",
              "sub": "no ACL to carry",
              "kind": "security"
            }
          ],
          [
            {
              "label": "24 hours",
              "sub": "external class"
            }
          ],
          [
            {
              "label": "Readability plus Tika",
              "sub": "boilerplate stripped"
            }
          ]
        ]
      }
    ],
    "note": "Databricks is deliberately not indexed. A number that can be computed correctly on demand should never be embedded and allowed to go stale.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "15-model-portfolio",
    "title": "Model Portfolio — Which Model Does Which Job, and What It Costs",
    "layout": "swimlane",
    "canvas": {
      "width": 1800
    },
    "laneHeaderWidth": 210,
    "stages": [
      "Model chosen",
      "Runs on",
      "Cost and latency",
      "Fallback"
    ],
    "lanes": [
      {
        "title": "Intent and rewrite",
        "cells": [
          [
            {
              "label": "Qwen3-8B-Instruct",
              "sub": "open weights"
            }
          ],
          [
            {
              "label": "vLLM on AKS GPU",
              "sub": "2 x A10, shared"
            }
          ],
          [
            {
              "label": "0.0002 USD, 90 ms",
              "sub": "per query"
            }
          ],
          [
            {
              "label": "Rules and the raw query",
              "sub": "no rewrite is safe",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Embedding",
        "cells": [
          [
            {
              "label": "BGE-M3",
              "sub": "dense and sparse"
            }
          ],
          [
            {
              "label": "TEI on AKS GPU",
              "sub": "batch and online"
            }
          ],
          [
            {
              "label": "0.00004 USD, 12 ms",
              "sub": "per query"
            }
          ],
          [
            {
              "label": "Lexical only retrieval",
              "sub": "recall drops, still serves",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Reranking",
        "cells": [
          [
            {
              "label": "bge-reranker-v2-m3",
              "sub": "cross-encoder"
            }
          ],
          [
            {
              "label": "TEI on AKS GPU",
              "sub": "top 50 in one batch"
            }
          ],
          [
            {
              "label": "0.0006 USD, 110 ms",
              "sub": "per query"
            }
          ],
          [
            {
              "label": "Fusion order only",
              "sub": "quality gate records it",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Answer synthesis",
        "cells": [
          [
            {
              "label": "Azure OpenAI, large tier",
              "sub": "quality-routed"
            }
          ],
          [
            {
              "label": "Azure AI Foundry",
              "sub": "PTU plus pay-go spill"
            }
          ],
          [
            {
              "label": "0.014 USD, 2.4 s",
              "sub": "P50 explanatory"
            }
          ],
          [
            {
              "label": "Smaller tier, then extractive",
              "sub": "never no answer",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Grounding verification",
        "cells": [
          [
            {
              "label": "NLI cross-encoder",
              "sub": "open weights, fine-tuned"
            }
          ],
          [
            {
              "label": "TEI on AKS GPU",
              "sub": "one call per claim"
            }
          ],
          [
            {
              "label": "0.0009 USD, 180 ms",
              "sub": "per answer"
            }
          ],
          [
            {
              "label": "Content Safety groundedness",
              "sub": "managed, slower",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Multimodal",
        "cells": [
          [
            {
              "label": "Azure AI Vision embeddings",
              "sub": "plus Whisper for audio"
            }
          ],
          [
            {
              "label": "Managed plus AKS GPU",
              "sub": "ingest-time mostly"
            }
          ],
          [
            {
              "label": "0.003 USD, 400 ms",
              "sub": "per query with media"
            }
          ],
          [
            {
              "label": "Caption text retrieval",
              "sub": "degraded but useful",
              "kind": "decision"
            }
          ]
        ]
      }
    ],
    "note": "Every task names a model and a fallback. The gateway can move a task between them by configuration; no service holds a model name in its code.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "16-knowledge-ingestion-pipeline",
    "title": "Knowledge Ingestion — From a Change in a Source to a Retrievable Chunk",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1860
    },
    "stages": [
      {
        "title": "Detect",
        "nodes": [
          {
            "id": "cn",
            "label": "Connector",
            "sub": "delta token per source"
          },
          {
            "id": "chg",
            "label": "Change Event",
            "sub": "Event Hubs",
            "kind": "queue"
          },
          {
            "id": "wq",
            "label": "Work Queue",
            "sub": "Service Bus, per class",
            "kind": "queue"
          },
          {
            "id": "tomb",
            "label": "Deletion Detected",
            "sub": "tombstone, not a gap",
            "kind": "decision"
          }
        ]
      },
      {
        "title": "Acquire",
        "nodes": [
          {
            "id": "fetch",
            "label": "Fetch Content",
            "sub": "throttle-aware"
          },
          {
            "id": "hash",
            "label": "Content Hash",
            "sub": "skip if unchanged"
          },
          {
            "id": "dedup",
            "label": "Dedup and Canonicalise",
            "sub": "SimHash near-duplicates"
          },
          {
            "id": "rawz",
            "label": "Raw Store",
            "sub": "ADLS Gen2, immutable",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Parse",
        "nodes": [
          {
            "id": "tika",
            "label": "Text and Office Parse",
            "sub": "Apache Tika"
          },
          {
            "id": "ocr",
            "label": "Layout OCR",
            "sub": "Document Intelligence"
          },
          {
            "id": "asr",
            "label": "Transcribe",
            "sub": "Whisper, timestamped",
            "icon": "fa5_microphone"
          },
          {
            "id": "tabl",
            "label": "Table and Figure Extract",
            "sub": "kept as units"
          }
        ]
      },
      {
        "title": "Enrich",
        "nodes": [
          {
            "id": "nerx",
            "label": "Entity Extraction",
            "sub": "to the graph"
          },
          {
            "id": "tax",
            "label": "Taxonomy Classify",
            "sub": "domain and doc type"
          },
          {
            "id": "pii",
            "label": "PII and Sensitivity",
            "sub": "Presidio plus labels",
            "kind": "security"
          },
          {
            "id": "inj",
            "label": "Injection Screen",
            "sub": "at index, not only at query",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Segment",
        "nodes": [
          {
            "id": "seg",
            "label": "Structure-Aware Chunking",
            "sub": "per type, view 18"
          },
          {
            "id": "hdr",
            "label": "Context Header",
            "sub": "title and heading path"
          },
          {
            "id": "ovl",
            "label": "Overlap Policy",
            "sub": "15% on prose only"
          }
        ]
      },
      {
        "title": "Represent",
        "nodes": [
          {
            "id": "dse",
            "label": "Dense and Sparse Vectors",
            "sub": "BGE-M3, versioned"
          },
          {
            "id": "mmv",
            "label": "Multimodal Vectors",
            "sub": "figures and frames"
          },
          {
            "id": "summ",
            "label": "Chunk Summary",
            "sub": "for long tables only"
          }
        ]
      },
      {
        "title": "Publish",
        "nodes": [
          {
            "id": "ups",
            "label": "Idempotent Upsert",
            "sub": "Azure AI Search",
            "kind": "store"
          },
          {
            "id": "gup",
            "label": "Graph Upsert",
            "sub": "entities and supersession",
            "kind": "store"
          },
          {
            "id": "led",
            "label": "Ledger Commit",
            "sub": "PostgreSQL, the receipt",
            "kind": "store"
          },
          {
            "id": "inv",
            "label": "Cache Invalidate",
            "sub": "by document and ACL",
            "kind": "store",
            "icon": "azure_cache-redis"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "tomb",
        "to": "ups",
        "label": "delete then invalidate",
        "kind": "error",
        "route": "gutter"
      },
      {
        "from": "hash",
        "to": "led",
        "label": "no change",
        "kind": "batch",
        "route": "gutter"
      }
    ],
    "note": "Every stage writes a receipt to the ledger. A document that fails at any stage is visible to its steward rather than silently absent.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "17-storage-zones",
    "title": "Storage Zones — What Can Be Rebuilt, and What Cannot",
    "layout": "nested",
    "canvas": {
      "width": 1840
    },
    "boxes": [
      {
        "title": "Zone 1 — Raw and immutable · source bytes as received",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Content",
            "kind": "plain",
            "nodes": [
              {
                "label": "Raw content",
                "sub": "ADLS Gen2, 12 TB",
                "kind": "store"
              },
              {
                "label": "Rendered pages",
                "sub": "page images for citation",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Why it exists",
            "kind": "plain",
            "nodes": [
              {
                "label": "Reparse without refetching",
                "sub": "source throttles are real"
              },
              {
                "label": "Citation anchors to a page",
                "sub": "not to a moving document"
              }
            ]
          }
        ]
      },
      {
        "title": "Zone 2 — Derived and rebuildable · deletable at any time, cost is only time",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Artefacts",
            "kind": "plain",
            "nodes": [
              {
                "label": "Parsed text",
                "sub": "Delta on ADLS",
                "kind": "store"
              },
              {
                "label": "Chunk table",
                "sub": "320 M rows",
                "kind": "store"
              },
              {
                "label": "Vectors and index",
                "sub": "Azure AI Search",
                "kind": "store"
              },
              {
                "label": "Graph projection",
                "sub": "Apache AGE",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Rebuild economics",
            "kind": "plain",
            "nodes": [
              {
                "label": "Full rebuild 14 hours",
                "sub": "1,900 USD of GPU"
              },
              {
                "label": "Single source rebuild",
                "sub": "under 2 hours"
              }
            ]
          }
        ]
      },
      {
        "title": "Zone 3 — Authoritative to the platform · nothing else can recreate it",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Records",
            "kind": "plain",
            "nodes": [
              {
                "label": "Document and version ledger",
                "sub": "PostgreSQL",
                "kind": "store"
              },
              {
                "label": "Answer provenance",
                "sub": "claims and evidence ids",
                "kind": "store"
              },
              {
                "label": "Feedback and labels",
                "sub": "the golden set grows here",
                "kind": "store"
              },
              {
                "label": "Audit record",
                "sub": "who asked, what was shown",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Consequence",
            "kind": "plain",
            "nodes": [
              {
                "label": "Backed up, geo-redundant",
                "sub": "RPO 5 minutes",
                "kind": "security"
              },
              {
                "label": "The only zone with an RPO",
                "sub": "everything else rebuilds",
                "kind": "decision"
              }
            ]
          }
        ]
      },
      {
        "title": "Zone 4 — Ephemeral · correctness must not depend on it",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Caches and state",
            "kind": "plain",
            "nodes": [
              {
                "label": "Answer and embedding cache",
                "sub": "Redis, TTL by class",
                "kind": "store",
                "icon": "azure_cache-redis"
              },
              {
                "label": "Conversation state",
                "sub": "30 days, then gone",
                "kind": "store"
              },
              {
                "label": "Traces",
                "sub": "Langfuse, 90 days",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Rule",
            "kind": "plain",
            "nodes": [
              {
                "label": "Flushing it degrades latency only",
                "sub": "never an answer",
                "kind": "decision"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "label": "Source systems keep owning the truth",
        "sub": "the platform holds no original",
        "kind": "external"
      }
    ],
    "note": "Deleting zones 1, 2 and 4 costs money and hours. Deleting zone 3 loses evidence that no source system can return, which is why only it is replicated.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "18-chunking-and-representation",
    "title": "Chunking and Representation — One Strategy per Content Type",
    "layout": "swimlane",
    "canvas": {
      "width": 1840
    },
    "laneHeaderWidth": 200,
    "stages": [
      "Unit of meaning",
      "How it is segmented",
      "What travels with it",
      "How it is represented"
    ],
    "lanes": [
      {
        "title": "Policy and Office documents",
        "cells": [
          [
            {
              "label": "A clause or subsection"
            }
          ],
          [
            {
              "label": "Heading path, 800 tokens",
              "sub": "15% overlap"
            }
          ],
          [
            {
              "label": "Title, heading trail, version",
              "sub": "effective dates"
            }
          ],
          [
            {
              "label": "Dense plus sparse",
              "sub": "BGE-M3"
            }
          ]
        ]
      },
      {
        "title": "Scanned PDF",
        "cells": [
          [
            {
              "label": "A page region"
            }
          ],
          [
            {
              "label": "Layout blocks from OCR",
              "sub": "reading order restored"
            }
          ],
          [
            {
              "label": "Page number and bounding box",
              "sub": "citation anchor"
            }
          ],
          [
            {
              "label": "Dense plus page image vector"
            }
          ]
        ]
      },
      {
        "title": "Wiki and HTML",
        "cells": [
          [
            {
              "label": "A section under a heading"
            }
          ],
          [
            {
              "label": "DOM section split",
              "sub": "boilerplate stripped"
            }
          ],
          [
            {
              "label": "Space, labels, last editor"
            }
          ],
          [
            {
              "label": "Dense plus sparse"
            }
          ]
        ]
      },
      {
        "title": "Support articles",
        "cells": [
          [
            {
              "label": "The whole article"
            }
          ],
          [
            {
              "label": "Never split",
              "sub": "symptom needs the fix"
            }
          ],
          [
            {
              "label": "Product, version, resolution state"
            }
          ],
          [
            {
              "label": "Dense over article, sparse over title"
            }
          ]
        ]
      },
      {
        "title": "Tables and spreadsheets",
        "cells": [
          [
            {
              "label": "A row group with its header"
            }
          ],
          [
            {
              "label": "Header repeated per shard",
              "sub": "no orphan rows"
            }
          ],
          [
            {
              "label": "Sheet, units, as-of date"
            }
          ],
          [
            {
              "label": "Serialised text plus summary"
            }
          ]
        ]
      },
      {
        "title": "Slide decks",
        "cells": [
          [
            {
              "label": "A slide with its notes"
            }
          ],
          [
            {
              "label": "Per slide, never merged"
            }
          ],
          [
            {
              "label": "Deck title, slide number"
            }
          ],
          [
            {
              "label": "Text plus slide image vector"
            }
          ]
        ]
      },
      {
        "title": "Audio and video",
        "cells": [
          [
            {
              "label": "A topical passage"
            }
          ],
          [
            {
              "label": "Transcript segmented at pauses",
              "sub": "90 to 150 seconds"
            }
          ],
          [
            {
              "label": "Timecode, speaker, asset id"
            }
          ],
          [
            {
              "label": "Transcript vector plus keyframes"
            }
          ]
        ]
      }
    ],
    "note": "Chunking is the design, not a parameter. A support article split in half retrieves the symptom without the fix, which is the failure this table exists to prevent.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "19-evidence-data-model",
    "title": "Evidence Data Model — Provenance as a First-Class Structure",
    "layout": "er",
    "canvas": {
      "width": 1780,
      "cols": 4
    },
    "rowGap": 240,
    "entities": [
      {
        "id": "src",
        "name": "source",
        "row": 0,
        "col": 0,
        "attrs": [
          "source_id  PK",
          "kind  m365 | confluence | snow | archive | sql | web",
          "freshness_class",
          "ranking_policy"
        ]
      },
      {
        "id": "doc",
        "name": "document",
        "row": 0,
        "col": 1,
        "attrs": [
          "document_id  PK",
          "source_id  FK -> source",
          "external_id",
          "steward_upn",
          "classification",
          "retired_at"
        ]
      },
      {
        "id": "ver",
        "name": "document_version",
        "row": 0,
        "col": 2,
        "attrs": [
          "version_id  PK",
          "document_id  FK -> document",
          "content_hash",
          "effective_from",
          "superseded_by  FK -> document_version",
          "indexed_at"
        ]
      },
      {
        "id": "acl",
        "name": "acl_grant",
        "row": 0,
        "col": 3,
        "attrs": [
          "grant_id  PK",
          "document_id  FK -> document",
          "principal_oid",
          "effect  allow | deny",
          "synced_at"
        ]
      },
      {
        "id": "chunk",
        "name": "chunk",
        "row": 1,
        "col": 1,
        "attrs": [
          "chunk_id  PK",
          "version_id  FK -> document_version",
          "ordinal",
          "heading_path",
          "page_no",
          "bbox",
          "modality"
        ]
      },
      {
        "id": "rep",
        "name": "representation",
        "row": 1,
        "col": 0,
        "attrs": [
          "rep_id  PK",
          "chunk_id  FK -> chunk",
          "model_name",
          "model_version",
          "kind  dense | sparse | image",
          "index_alias"
        ]
      },
      {
        "id": "ent",
        "name": "entity",
        "row": 1,
        "col": 3,
        "attrs": [
          "entity_id  PK",
          "canonical_name",
          "type",
          "aliases"
        ]
      },
      {
        "id": "men",
        "name": "entity_mention",
        "row": 1,
        "col": 2,
        "attrs": [
          "mention_id  PK",
          "chunk_id  FK -> chunk",
          "entity_id  FK -> entity",
          "confidence"
        ]
      },
      {
        "id": "qry",
        "name": "query",
        "row": 2,
        "col": 0,
        "attrs": [
          "query_id  PK",
          "principal_oid",
          "acl_fingerprint",
          "class",
          "asked_at",
          "conversation_id"
        ]
      },
      {
        "id": "plan",
        "name": "query_plan",
        "row": 2,
        "col": 1,
        "attrs": [
          "plan_id  PK",
          "query_id  FK -> query",
          "sub_queries  jsonb",
          "backends  jsonb",
          "budget  jsonb"
        ]
      },
      {
        "id": "res",
        "name": "retrieval_result",
        "row": 2,
        "col": 2,
        "attrs": [
          "evidence_id  PK",
          "plan_id  FK -> query_plan",
          "chunk_id  FK -> chunk",
          "backend",
          "raw_score",
          "rank_after_fusion",
          "reason"
        ]
      },
      {
        "id": "ans",
        "name": "answer",
        "row": 2,
        "col": 3,
        "attrs": [
          "answer_id  PK",
          "query_id  FK -> query",
          "model_name",
          "tokens_in",
          "tokens_out",
          "groundedness",
          "state  answered | abstained | fallback"
        ]
      },
      {
        "id": "clm",
        "name": "claim",
        "row": 3,
        "col": 2,
        "attrs": [
          "claim_id  PK",
          "answer_id  FK -> answer",
          "sentence_ordinal",
          "verdict  supported | unsupported | contradicted",
          "nli_score"
        ]
      },
      {
        "id": "cit",
        "name": "citation",
        "row": 3,
        "col": 1,
        "attrs": [
          "citation_id  PK",
          "claim_id  FK -> claim",
          "evidence_id  FK -> retrieval_result",
          "quote_span"
        ]
      },
      {
        "id": "fb",
        "name": "feedback",
        "row": 3,
        "col": 3,
        "attrs": [
          "feedback_id  PK",
          "answer_id  FK -> answer",
          "signal  useful | wrong | unclear",
          "note",
          "promoted_to_golden"
        ]
      }
    ],
    "relations": [
      {
        "from": "src",
        "to": "doc",
        "label": "1 : N",
        "from_side": "e",
        "to_side": "w"
      },
      {
        "from": "doc",
        "to": "ver",
        "label": "1 : N",
        "from_side": "e",
        "to_side": "w"
      },
      {
        "from": "doc",
        "to": "acl",
        "label": "1 : N",
        "from_side": "n",
        "to_side": "n"
      },
      {
        "from": "ver",
        "to": "chunk",
        "label": "1 : N",
        "from_side": "s",
        "to_side": "n"
      },
      {
        "from": "chunk",
        "to": "rep",
        "label": "1 : N",
        "from_side": "w",
        "to_side": "e"
      },
      {
        "from": "chunk",
        "to": "men",
        "label": "1 : N",
        "from_side": "e",
        "to_side": "w"
      },
      {
        "from": "ent",
        "to": "men",
        "label": "1 : N",
        "from_side": "w",
        "to_side": "e"
      },
      {
        "from": "qry",
        "to": "plan",
        "label": "1 : 1",
        "from_side": "e",
        "to_side": "w"
      },
      {
        "from": "plan",
        "to": "res",
        "label": "1 : N",
        "from_side": "e",
        "to_side": "w"
      },
      {
        "from": "chunk",
        "to": "res",
        "label": "1 : N",
        "from_side": "s3",
        "to_side": "n1"
      },
      {
        "from": "qry",
        "to": "ans",
        "label": "1 : N",
        "from_side": "s",
        "to_side": "s1"
      },
      {
        "from": "ans",
        "to": "clm",
        "label": "1 : N",
        "from_side": "s1",
        "to_side": "n"
      },
      {
        "from": "clm",
        "to": "cit",
        "label": "1 : N",
        "from_side": "w",
        "to_side": "e"
      },
      {
        "from": "res",
        "to": "cit",
        "label": "1 : N",
        "from_side": "s1",
        "to_side": "n"
      },
      {
        "from": "ans",
        "to": "fb",
        "label": "1 : N",
        "from_side": "s3",
        "to_side": "n"
      }
    ],
    "note": "A citation joins a claim to a retrieval_result, never straight to a chunk. That single join is what makes an answer replayable and an audit answerable.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "20-permission-propagation",
    "title": "Permission Propagation — How Authorisation Travels With the Data",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1820
    },
    "stages": [
      {
        "title": "At the source",
        "nodes": [
          {
            "id": "nacl",
            "label": "Native ACL",
            "sub": "item and folder",
            "kind": "security"
          },
          {
            "id": "grp",
            "label": "Group membership",
            "sub": "Entra, nested",
            "kind": "security"
          },
          {
            "id": "lbl",
            "label": "Sensitivity label",
            "sub": "Purview",
            "kind": "security"
          }
        ]
      },
      {
        "title": "At ingest",
        "nodes": [
          {
            "id": "xacl",
            "label": "ACL extraction",
            "sub": "with the content, not after"
          },
          {
            "id": "norm",
            "label": "Principal normalisation",
            "sub": "everything to an object id"
          },
          {
            "id": "den",
            "label": "Deny capture",
            "sub": "deny beats allow",
            "kind": "decision"
          },
          {
            "id": "cls",
            "label": "Classification mapped",
            "sub": "label to ceiling"
          }
        ]
      },
      {
        "title": "In the index",
        "nodes": [
          {
            "id": "fa",
            "label": "acl_allow[]",
            "sub": "object ids",
            "kind": "store",
            "icon": "fa5_key"
          },
          {
            "id": "fd",
            "label": "acl_deny[]",
            "sub": "evaluated first",
            "kind": "store",
            "icon": "fa5_ban"
          },
          {
            "id": "fc",
            "label": "classification",
            "sub": "filterable",
            "kind": "store",
            "icon": "fa5_tags"
          },
          {
            "id": "ft",
            "label": "tenant and region",
            "sub": "hard partition",
            "kind": "store",
            "icon": "fa5_building"
          }
        ]
      },
      {
        "title": "At query",
        "nodes": [
          {
            "id": "obo",
            "label": "On-behalf-of token",
            "sub": "never a service identity",
            "kind": "security"
          },
          {
            "id": "exp",
            "label": "Group set expanded",
            "sub": "transitive, cached 60 s",
            "kind": "security"
          },
          {
            "id": "flt",
            "label": "Filter composed",
            "sub": "index-side, pre-scoring",
            "kind": "security"
          }
        ]
      },
      {
        "title": "At render",
        "nodes": [
          {
            "id": "rc",
            "label": "Citation re-check",
            "sub": "at display time"
          },
          {
            "id": "ck",
            "label": "Cache key fingerprint",
            "sub": "principal group set",
            "kind": "store"
          },
          {
            "id": "aud",
            "label": "Audit record",
            "sub": "query, evidence, principal",
            "kind": "store"
          }
        ]
      },
      {
        "title": "On change",
        "nodes": [
          {
            "id": "dl",
            "label": "ACL delta job",
            "sub": "60 second target"
          },
          {
            "id": "ri",
            "label": "Targeted re-index",
            "sub": "fields only, not content"
          },
          {
            "id": "ic",
            "label": "Cache invalidation",
            "sub": "by principal and document",
            "kind": "store"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "dl",
        "to": "fa",
        "label": "field-level update",
        "kind": "async",
        "route": "gutter"
      }
    ],
    "note": "Post-filtering is banned. If the filter is applied after scoring, the ranked set already reveals what exists, and the top-k is quietly wrong.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "21-freshness-lifecycle",
    "title": "Freshness Lifecycle — Keeping the Index Honest About Time",
    "layout": "cycle",
    "centre": {
      "label": "Freshness Loop",
      "sub": "per source class"
    },
    "rx": 430,
    "ry": 220,
    "nodes": [
      {
        "label": "Change detected",
        "sub": "delta, CDC or crawl",
        "id": "f1"
      },
      {
        "label": "Prioritised",
        "sub": "by freshness class",
        "kind": "decision",
        "id": "f2"
      },
      {
        "label": "Reprocessed",
        "sub": "only what changed",
        "id": "f3"
      },
      {
        "label": "Republished",
        "sub": "idempotent upsert",
        "kind": "store",
        "id": "f4"
      },
      {
        "label": "Probed",
        "sub": "canary query per source",
        "id": "f5"
      },
      {
        "label": "Superseded",
        "sub": "old version demoted",
        "id": "f6"
      },
      {
        "label": "Staleness published",
        "sub": "as-of on every answer",
        "kind": "platform",
        "id": "f7"
      }
    ],
    "ringLabels": [
      "queued",
      "5 min or 24 h",
      "parse and embed",
      "alias swap",
      "found or alarmed",
      "graph edge written",
      "back to watching"
    ],
    "note": "Staleness is never hidden. Where a source is behind its class, the answer says so rather than reading as current.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "22-ask-to-answer-sequence",
    "title": "Ask to Answer — The Critical Path, One Request",
    "layout": "sequence",
    "canvas": {
      "width": 1780
    },
    "lifelines": [
      {
        "id": "u",
        "label": "Knowledge Worker",
        "kind": "actor"
      },
      {
        "id": "gw",
        "label": "Search Gateway"
      },
      {
        "id": "qu",
        "label": "Query Understanding"
      },
      {
        "id": "pl",
        "label": "Planner"
      },
      {
        "id": "rf",
        "label": "Retriever Facade",
        "icon": "fa5_random"
      },
      {
        "id": "ix",
        "label": "Azure AI Search",
        "kind": "store",
        "icon": "azure_search"
      },
      {
        "id": "mg",
        "label": "Model Gateway",
        "kind": "integration"
      },
      {
        "id": "vf",
        "label": "Verifier",
        "kind": "security",
        "icon": "fa5_check_double"
      }
    ],
    "messages": [
      {
        "from": "u",
        "to": "gw",
        "label": "POST /v1/answer",
        "kind": "call"
      },
      {
        "from": "gw",
        "to": "gw",
        "label": "validate OBO token, start trace",
        "kind": "self"
      },
      {
        "from": "gw",
        "to": "qu",
        "label": "interpret and authorise",
        "kind": "call"
      },
      {
        "from": "qu",
        "to": "qu",
        "label": "class, entities, group set, fingerprint",
        "kind": "self"
      },
      {
        "from": "qu",
        "to": "pl",
        "label": "QueryPlan",
        "kind": "return"
      },
      {
        "from": "pl",
        "to": "rf",
        "label": "retrieve, depth 80",
        "kind": "call"
      },
      {
        "from": "rf",
        "to": "ix",
        "label": "hybrid query with ACL filter",
        "kind": "call"
      },
      {
        "from": "ix",
        "to": "rf",
        "label": "94 candidates",
        "kind": "return"
      },
      {
        "from": "rf",
        "to": "rf",
        "label": "fuse, rerank, diversify",
        "kind": "self"
      },
      {
        "from": "rf",
        "to": "pl",
        "label": "8 evidence items",
        "kind": "return"
      },
      {
        "from": "pl",
        "to": "mg",
        "label": "synthesise over fenced evidence",
        "kind": "call"
      },
      {
        "from": "mg",
        "to": "gw",
        "label": "first token, 1.2 s",
        "kind": "async"
      },
      {
        "from": "mg",
        "to": "pl",
        "label": "draft with claim markers",
        "kind": "return"
      },
      {
        "from": "pl",
        "to": "vf",
        "label": "verify claims against evidence",
        "kind": "call"
      },
      {
        "from": "vf",
        "to": "pl",
        "label": "one claim unsupported",
        "kind": "error"
      },
      {
        "from": "pl",
        "to": "rf",
        "label": "targeted re-retrieval, hop 2",
        "kind": "call"
      },
      {
        "from": "rf",
        "to": "pl",
        "label": "2 further items",
        "kind": "return"
      },
      {
        "from": "pl",
        "to": "vf",
        "label": "re-verify",
        "kind": "call"
      },
      {
        "from": "vf",
        "to": "pl",
        "label": "all claims supported",
        "kind": "return"
      },
      {
        "from": "pl",
        "to": "gw",
        "label": "answer, citations, provenance",
        "kind": "return"
      },
      {
        "from": "gw",
        "to": "u",
        "label": "stream completed, 4.1 s",
        "kind": "return"
      }
    ],
    "note": "The unsupported claim on message 15 is the normal case, not the exception. Budget allows one extra hop; a second failure abstains rather than guessing.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "23-agentic-loop",
    "title": "The Bounded Agentic Loop — Where the Model Is Allowed to Decide",
    "layout": "cycle",
    "centre": {
      "label": "Bounded Loop",
      "sub": "3 hops, 18 s"
    },
    "rx": 430,
    "ry": 225,
    "nodes": [
      {
        "id": "a1",
        "label": "Understand",
        "sub": "class and entities"
      },
      {
        "id": "a2",
        "label": "Plan",
        "sub": "sub-queries, backends",
        "icon": "fa5_project_diagram"
      },
      {
        "id": "a3",
        "label": "Retrieve",
        "sub": "policy-filtered",
        "kind": "store"
      },
      {
        "id": "a4",
        "label": "Evaluate evidence",
        "sub": "coverage and conflict",
        "kind": "decision"
      },
      {
        "id": "a5",
        "label": "Refine or stop",
        "sub": "budget decides",
        "kind": "decision"
      },
      {
        "id": "a6",
        "label": "Synthesise",
        "sub": "claims, not prose"
      },
      {
        "id": "a7",
        "label": "Verify",
        "sub": "grounding and safety",
        "kind": "security"
      }
    ],
    "ringLabels": [
      "typed plan",
      "retrieval requests",
      "candidates and reasons",
      "gap named, not felt",
      "one more hop, or enough",
      "draft with claim markers",
      "answer, abstain or fall back"
    ],
    "note": "The model chooses what to ask for. It never chooses what it may see, how long it may run, or whether its answer ships.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "24-hybrid-retrieval-and-fusion",
    "title": "Hybrid Retrieval and Fusion — From Four Candidate Sets to Eight Passages",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1820
    },
    "stages": [
      {
        "title": "Prepare",
        "nodes": [
          {
            "id": "pq",
            "label": "Plan and filters",
            "sub": "ACL, source, freshness"
          },
          {
            "id": "var",
            "label": "Query variants",
            "sub": "up to 4"
          },
          {
            "id": "emq",
            "label": "Query embedding",
            "sub": "BGE-M3, cached"
          }
        ]
      },
      {
        "title": "Generate candidates",
        "nodes": [
          {
            "id": "c1",
            "label": "Lexical BM25",
            "sub": "top 100",
            "kind": "store"
          },
          {
            "id": "c2",
            "label": "Dense vector",
            "sub": "top 100",
            "kind": "store"
          },
          {
            "id": "c3",
            "label": "Learned sparse",
            "sub": "top 60",
            "kind": "store"
          },
          {
            "id": "c4",
            "label": "Graph expansion",
            "sub": "top 40",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Fuse",
        "nodes": [
          {
            "id": "rrf",
            "label": "Reciprocal rank fusion",
            "sub": "k = 60"
          },
          {
            "id": "wts",
            "label": "Source authority weights",
            "sub": "policy, not tuning"
          },
          {
            "id": "dd",
            "label": "Near-duplicate collapse",
            "sub": "SimHash on passages"
          }
        ]
      },
      {
        "title": "Rerank",
        "nodes": [
          {
            "id": "ce",
            "label": "Cross-encoder",
            "sub": "top 50 scored"
          },
          {
            "id": "cut",
            "label": "Score floor",
            "sub": "0.32, tuned on golden set",
            "kind": "decision"
          },
          {
            "id": "fr",
            "label": "Freshness adjustment",
            "sub": "class-aware, bounded"
          }
        ]
      },
      {
        "title": "Diversify",
        "nodes": [
          {
            "id": "mmr",
            "label": "Maximal marginal relevance",
            "sub": "lambda 0.7"
          },
          {
            "id": "cap",
            "label": "Two passages per document",
            "sub": "hard cap"
          },
          {
            "id": "cov",
            "label": "Sub-query coverage check",
            "sub": "each hop represented",
            "kind": "decision"
          }
        ]
      },
      {
        "title": "Select evidence",
        "nodes": [
          {
            "id": "tb",
            "label": "Token budget fit",
            "sub": "8 passages, 6k tokens"
          },
          {
            "id": "eid",
            "label": "Evidence ids minted",
            "sub": "chunk plus version"
          },
          {
            "id": "why",
            "label": "Retrieval reason recorded",
            "sub": "for the trace",
            "kind": "platform"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "cov",
        "to": "pq",
        "label": "re-plan",
        "kind": "error",
        "route": "gutter"
      },
      {
        "from": "cut",
        "to": "tb",
        "label": "dropped",
        "kind": "batch",
        "route": "gutter"
      }
    ],
    "note": "Vector-only retrieval failed the golden set on part numbers and policy identifiers, which is why the lexical arm is not an option in the configuration.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "25-context-assembly",
    "title": "Context Assembly — What Occupies the Window, and Under What Rules",
    "layout": "grid",
    "canvas": {
      "width": 1840
    },
    "laneHeaderWidth": 210,
    "columns": [
      "Where it comes from",
      "Trust level",
      "Token budget",
      "When the window is short"
    ],
    "rows": [
      {
        "title": "System policy",
        "cells": [
          [
            {
              "label": "Versioned prompt registry",
              "sub": "reviewed like code"
            }
          ],
          [
            {
              "label": "Trusted",
              "sub": "the only instructions",
              "kind": "security",
              "icon": "fa5_shield_alt"
            }
          ],
          [
            {
              "label": "700 tokens",
              "sub": "fixed",
              "icon": false
            }
          ],
          [
            {
              "label": "Never trimmed",
              "sub": "request fails first",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Task and output schema",
        "cells": [
          [
            {
              "label": "Query class template",
              "sub": "one per class"
            }
          ],
          [
            {
              "label": "Trusted",
              "sub": "server-composed",
              "kind": "security",
              "icon": "fa5_shield_alt"
            }
          ],
          [
            {
              "label": "400 tokens",
              "sub": "fixed",
              "icon": false
            }
          ],
          [
            {
              "label": "Never trimmed",
              "sub": "schema is the contract",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Conversation state",
        "cells": [
          [
            {
              "label": "Last 6 turns, summarised",
              "sub": "PostgreSQL",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Semi-trusted",
              "sub": "the caller wrote it"
            }
          ],
          [
            {
              "label": "800 tokens",
              "sub": "rolling summary",
              "icon": false
            }
          ],
          [
            {
              "label": "Summarise harder",
              "sub": "oldest turns first"
            }
          ]
        ]
      },
      {
        "title": "Retrieved evidence",
        "cells": [
          [
            {
              "label": "Evidence set, 8 passages",
              "sub": "each with an id",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Untrusted data",
              "sub": "fenced, never obeyed",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "6,000 tokens",
              "sub": "the majority share",
              "icon": false
            }
          ],
          [
            {
              "label": "Drop lowest-ranked passage",
              "sub": "and say the set was cut",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "Tool results",
        "cells": [
          [
            {
              "label": "Broker output, typed",
              "sub": "SQL rows, calculations"
            }
          ],
          [
            {
              "label": "Untrusted data",
              "sub": "same fence as evidence",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "1,200 tokens",
              "sub": "rows truncated with a count",
              "icon": false
            }
          ],
          [
            {
              "label": "Aggregate, never sample",
              "sub": "a sample misleads",
              "kind": "decision"
            }
          ]
        ]
      },
      {
        "title": "The caller turn",
        "cells": [
          [
            {
              "label": "This question, verbatim",
              "sub": "plus resolved scope"
            }
          ],
          [
            {
              "label": "Trusted as intent",
              "sub": "not as instruction to tools",
              "kind": "security",
              "icon": "fa5_shield_alt"
            }
          ],
          [
            {
              "label": "300 tokens",
              "sub": "truncated with notice",
              "icon": false
            }
          ],
          [
            {
              "label": "Never trimmed",
              "sub": "it is the question",
              "kind": "decision"
            }
          ]
        ]
      }
    ],
    "note": "Compression happens on evidence and history, never on policy or the question. A window that cannot hold the fixed slots is a routing failure, not a prompt problem.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "26-grounding-and-verification",
    "title": "Grounding and Verification — Turning a Draft Into Claims That Hold",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1820
    },
    "stages": [
      {
        "title": "Draft",
        "nodes": [
          {
            "id": "d1",
            "label": "Model output",
            "sub": "structured, claim-marked"
          },
          {
            "id": "d2",
            "label": "Schema validation",
            "sub": "reject and retry once",
            "kind": "decision"
          }
        ]
      },
      {
        "title": "Decompose",
        "nodes": [
          {
            "id": "s1",
            "label": "Claim segmentation",
            "sub": "one assertion per claim"
          },
          {
            "id": "s2",
            "label": "Numeric and date extraction",
            "sub": "checked literally"
          },
          {
            "id": "s3",
            "label": "Quote span capture",
            "sub": "for the citation anchor"
          }
        ]
      },
      {
        "title": "Align",
        "nodes": [
          {
            "id": "n1",
            "label": "Claim to evidence NLI",
            "sub": "cross-encoder, per pair"
          },
          {
            "id": "n2",
            "label": "Numeric equality check",
            "sub": "deterministic, not model"
          },
          {
            "id": "n3",
            "label": "Cross-source agreement",
            "sub": "pairwise on claims"
          }
        ]
      },
      {
        "title": "Judge",
        "nodes": [
          {
            "id": "v1",
            "label": "Supported",
            "sub": "score above 0.72",
            "kind": "decision"
          },
          {
            "id": "v2",
            "label": "Unsupported",
            "sub": "no evidence covers it",
            "kind": "risk"
          },
          {
            "id": "v3",
            "label": "Contradicted",
            "sub": "sources disagree",
            "kind": "risk"
          }
        ]
      },
      {
        "title": "Act",
        "nodes": [
          {
            "id": "a1",
            "label": "Cite and keep",
            "sub": "evidence id bound"
          },
          {
            "id": "a2",
            "label": "Re-retrieve once",
            "sub": "targeted at the gap"
          },
          {
            "id": "a3",
            "label": "Drop or abstain",
            "sub": "budget exhausted",
            "kind": "risk"
          },
          {
            "id": "a4",
            "label": "Show both positions",
            "sub": "dated and attributed"
          }
        ]
      },
      {
        "title": "Present",
        "nodes": [
          {
            "id": "p1",
            "label": "Claim-level citations",
            "sub": "anchored to a passage"
          },
          {
            "id": "p2",
            "label": "Confidence and as-of",
            "sub": "stated, not implied"
          },
          {
            "id": "p3",
            "label": "Disagreement banner",
            "sub": "when sources conflict"
          },
          {
            "id": "p4",
            "label": "Provenance persisted",
            "sub": "replayable",
            "kind": "store"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "v2",
        "to": "a2",
        "label": "gap",
        "kind": "error"
      },
      {
        "from": "v3",
        "to": "a4",
        "label": "conflict",
        "kind": "error"
      }
    ],
    "note": "Groundedness is measured against the evidence actually supplied, not against the world. A claim that is true but unsupported here is still dropped.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "27-structured-retrieval-and-tools",
    "title": "Structured Retrieval and Tool Invocation — The Model Asks, the Broker Decides",
    "layout": "sequence",
    "canvas": {
      "width": 1720
    },
    "lifelines": [
      {
        "id": "pl",
        "label": "Planner"
      },
      {
        "id": "tb",
        "label": "Tool Broker",
        "kind": "integration",
        "icon": "fa5_toolbox"
      },
      {
        "id": "pe",
        "label": "Policy Engine",
        "kind": "security"
      },
      {
        "id": "sg",
        "label": "SQL Guard",
        "kind": "security"
      },
      {
        "id": "dbx",
        "label": "Databricks SQL",
        "kind": "external"
      },
      {
        "id": "as",
        "label": "Answer Assembler",
        "icon": "fa5_puzzle_piece"
      },
      {
        "id": "au",
        "label": "Audit Log",
        "kind": "store"
      }
    ],
    "messages": [
      {
        "from": "pl",
        "to": "tb",
        "label": "tool request: revenue by region, FY26",
        "kind": "call"
      },
      {
        "from": "tb",
        "to": "pe",
        "label": "may this class call this tool?",
        "kind": "call"
      },
      {
        "from": "pe",
        "to": "tb",
        "label": "allowed: structured class, read-only",
        "kind": "return"
      },
      {
        "from": "tb",
        "to": "tb",
        "label": "reject if the request came from a document",
        "kind": "self"
      },
      {
        "from": "tb",
        "to": "sg",
        "label": "compile against the semantic layer",
        "kind": "call"
      },
      {
        "from": "sg",
        "to": "sg",
        "label": "allowlisted views, bound parameters, row cap",
        "kind": "self"
      },
      {
        "from": "sg",
        "to": "dbx",
        "label": "parameterised SQL as the caller",
        "kind": "call"
      },
      {
        "from": "dbx",
        "to": "sg",
        "label": "42 rows, Unity Catalog applied",
        "kind": "return"
      },
      {
        "from": "sg",
        "to": "tb",
        "label": "typed result plus the SQL executed",
        "kind": "return"
      },
      {
        "from": "tb",
        "to": "au",
        "label": "tool call, principal, statement",
        "kind": "async"
      },
      {
        "from": "tb",
        "to": "as",
        "label": "rows as citable evidence",
        "kind": "return"
      },
      {
        "from": "as",
        "to": "as",
        "label": "figures rendered from rows, never retyped",
        "kind": "self"
      }
    ],
    "note": "The model never emits SQL that reaches a database. It names an intent; the guard compiles it against views a data owner published.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "28-multimodal-retrieval",
    "title": "Multimodal Retrieval — Text, Image, Table, Audio and Video",
    "layout": "swimlane",
    "canvas": {
      "width": 1840
    },
    "laneHeaderWidth": 210,
    "stages": [
      "Represented at ingest",
      "Matched at query",
      "What is cited",
      "Known limit"
    ],
    "lanes": [
      {
        "title": "Figures in documents",
        "cells": [
          [
            {
              "label": "Image vector plus caption",
              "sub": "and surrounding text"
            }
          ],
          [
            {
              "label": "Text query to image space",
              "sub": "cross-modal"
            }
          ],
          [
            {
              "label": "Cropped figure, page anchored"
            }
          ],
          [
            {
              "label": "Dense schematics under-retrieve",
              "sub": "caption carries the recall",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Photo from the field",
        "cells": [
          [
            {
              "label": "Not indexed, it is the query"
            }
          ],
          [
            {
              "label": "Image to image plus OCR text",
              "sub": "asset tags read from the plate"
            }
          ],
          [
            {
              "label": "Matching procedure and revision"
            }
          ],
          [
            {
              "label": "Poor lighting drops OCR",
              "sub": "falls back to visual only",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Slides",
        "cells": [
          [
            {
              "label": "Slide image plus notes text"
            }
          ],
          [
            {
              "label": "Text first, image as a tie-break"
            }
          ],
          [
            {
              "label": "Slide thumbnail and number"
            }
          ],
          [
            {
              "label": "Design-heavy decks are noisy",
              "sub": "notes weighted higher",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Audio and video",
        "cells": [
          [
            {
              "label": "Transcript plus keyframe vectors",
              "sub": "timecoded"
            }
          ],
          [
            {
              "label": "Transcript retrieval, frame confirm"
            }
          ],
          [
            {
              "label": "Player deep-link at the timecode"
            }
          ],
          [
            {
              "label": "Speaker attribution is weak",
              "sub": "never used as authority",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Tables and forms",
        "cells": [
          [
            {
              "label": "Row groups plus a summary line"
            }
          ],
          [
            {
              "label": "Lexical on headers, dense on summary"
            }
          ],
          [
            {
              "label": "The row group, with its header"
            }
          ],
          [
            {
              "label": "Merged cells still mis-parse",
              "sub": "flagged to the steward",
              "kind": "risk"
            }
          ]
        ]
      }
    ],
    "note": "Every modality names its known limit. A modality with no stated limit has not been measured, and would be more dangerous than one that is simply weak.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "29-degradation-ladder",
    "title": "Degradation Ladder — What the User Still Gets When a Dependency Fails",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1840
    },
    "stages": [
      {
        "title": "Healthy",
        "nodes": [
          {
            "id": "h1",
            "label": "All backends up",
            "sub": "nothing failing"
          },
          {
            "id": "h2",
            "label": "Full generative answer",
            "sub": "claim-bound citations"
          },
          {
            "id": "h3",
            "label": "99.9% of minutes",
            "sub": "the SLO",
            "kind": "decision"
          }
        ]
      },
      {
        "title": "Rung 1 — model pressure",
        "nodes": [
          {
            "id": "r11",
            "label": "Azure OpenAI throttled",
            "sub": "429 or latency spike",
            "kind": "risk"
          },
          {
            "id": "r12",
            "label": "Route to smaller tier",
            "sub": "gateway policy",
            "kind": "decision"
          },
          {
            "id": "r13",
            "label": "Shorter answer, same citations",
            "sub": "user sees a notice",
            "kind": "journey"
          }
        ]
      },
      {
        "title": "Rung 2 — ranking loss",
        "nodes": [
          {
            "id": "r21",
            "label": "Rerank service down",
            "sub": "GPU pool unavailable",
            "kind": "risk"
          },
          {
            "id": "r22",
            "label": "Serve fusion order",
            "sub": "quality flag recorded",
            "kind": "decision"
          },
          {
            "id": "r23",
            "label": "Answer with wider evidence",
            "sub": "confidence lowered",
            "kind": "journey"
          }
        ]
      },
      {
        "title": "Rung 3 — semantic loss",
        "nodes": [
          {
            "id": "r31",
            "label": "Vector arm unavailable",
            "sub": "index or embed service",
            "kind": "risk"
          },
          {
            "id": "r32",
            "label": "Lexical-only retrieval",
            "sub": "recall drops to 0.71",
            "kind": "decision"
          },
          {
            "id": "r33",
            "label": "Extractive answer only",
            "sub": "no synthesis over gaps",
            "kind": "journey"
          }
        ]
      },
      {
        "title": "Rung 4 — index loss",
        "nodes": [
          {
            "id": "r41",
            "label": "Search service degraded",
            "sub": "region or partition",
            "kind": "risk"
          },
          {
            "id": "r42",
            "label": "Serve the cache, then fail over",
            "sub": "paired region alias",
            "kind": "decision"
          },
          {
            "id": "r43",
            "label": "Cached answers and links",
            "sub": "staleness stated",
            "kind": "journey"
          }
        ]
      },
      {
        "title": "Rung 5 — floor",
        "nodes": [
          {
            "id": "r51",
            "label": "Generation unavailable",
            "sub": "safety or policy stop",
            "kind": "risk"
          },
          {
            "id": "r52",
            "label": "Classic search API",
            "sub": "always deployable alone",
            "kind": "decision"
          },
          {
            "id": "r53",
            "label": "Ranked list of documents",
            "sub": "the product still works",
            "kind": "journey"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "r51",
        "to": "h3",
        "label": "search SLO is separate, 99.95%",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "The classic search API is deployable with no model, no GPU and no vector index. That is why the floor of this ladder is a working product rather than an error page.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "30-deployment-architecture",
    "title": "Deployment Architecture — Where It Runs and What Survives a Failure",
    "layout": "nested",
    "canvas": {
      "width": 1860
    },
    "boxes": [
      {
        "title": "Azure — West Europe (primary region)",
        "kind": "cloud",
        "dir": "col",
        "children": [
          {
            "title": "Hub VNet — edge and shared services",
            "kind": "boundary",
            "nodes": [
              {
                "id": "fd",
                "label": "Front Door and WAF",
                "sub": "TLS, bot rules",
                "kind": "security"
              },
              {
                "id": "apim",
                "label": "API Management",
                "sub": "quota, keys, versions",
                "kind": "integration"
              },
              {
                "id": "fw",
                "label": "Azure Firewall",
                "sub": "egress allowlist",
                "kind": "security"
              },
              {
                "id": "kv",
                "label": "Key Vault",
                "sub": "workload identity",
                "kind": "security"
              },
              {
                "id": "bas",
                "label": "Bastion",
                "sub": "no public admin",
                "kind": "security"
              }
            ]
          },
          {
            "title": "AKS spoke — application node pools, 3 availability zones",
            "kind": "boundary",
            "nodes": [
              {
                "id": "np1",
                "label": "Answer plane",
                "sub": "38 pods, D8s v5"
              },
              {
                "id": "np2",
                "label": "Retrieval plane",
                "sub": "26 pods, D8s v5"
              },
              {
                "id": "np3",
                "label": "Ingest plane",
                "sub": "autoscaled 4 to 60"
              },
              {
                "id": "np4",
                "label": "Platform plane",
                "sub": "gateway, policy, traces",
                "kind": "platform"
              }
            ]
          },
          {
            "title": "AKS spoke — GPU node pools",
            "kind": "boundary",
            "nodes": [
              {
                "id": "g1",
                "label": "Embed and rerank",
                "sub": "4 x A10, always on"
              },
              {
                "id": "g2",
                "label": "Verifier and small LLM",
                "sub": "2 x A10",
                "icon": "fa5_check_double"
              },
              {
                "id": "g3",
                "label": "Batch embedding",
                "sub": "6 x A10 spot, queue-driven"
              }
            ]
          },
          {
            "title": "Data services — private endpoints only",
            "kind": "boundary",
            "nodes": [
              {
                "id": "ais",
                "label": "Azure AI Search",
                "sub": "S3, 12 partitions, 3 replicas",
                "kind": "store",
                "icon": "azure_search"
              },
              {
                "id": "pg",
                "label": "PostgreSQL Flexible",
                "sub": "zone-redundant HA",
                "kind": "store"
              },
              {
                "id": "rd",
                "label": "Cache for Redis",
                "sub": "premium, zone-redundant",
                "kind": "store",
                "icon": "azure_cache-redis"
              },
              {
                "id": "st",
                "label": "ADLS Gen2",
                "sub": "ZRS, immutable raw",
                "kind": "store"
              },
              {
                "id": "eh",
                "label": "Event Hubs and Service Bus",
                "sub": "zone-redundant",
                "kind": "queue"
              }
            ]
          }
        ]
      },
      {
        "title": "Azure — North Europe (paired region, warm)",
        "kind": "cloud",
        "dir": "row",
        "children": [
          {
            "title": "Standby capacity",
            "kind": "boundary",
            "nodes": [
              {
                "id": "aks2",
                "label": "AKS minimal",
                "sub": "scales on failover"
              },
              {
                "id": "ais2",
                "label": "AI Search replica index",
                "sub": "indexer writes both",
                "kind": "store"
              },
              {
                "id": "pg2",
                "label": "PostgreSQL read replica",
                "sub": "promotable",
                "kind": "store"
              }
            ]
          },
          {
            "title": "Recovery targets",
            "kind": "plain",
            "nodes": [
              {
                "id": "rto",
                "label": "RTO 30 minutes",
                "sub": "search first, then answers",
                "kind": "decision"
              },
              {
                "id": "rpo",
                "label": "RPO 5 minutes",
                "sub": "ledger and provenance only",
                "kind": "decision"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "id": "aoai",
        "label": "Azure OpenAI",
        "sub": "two regions, one gateway",
        "kind": "external",
        "icon": "azure_openai"
      },
      {
        "id": "aad",
        "label": "Microsoft Entra ID",
        "sub": "global",
        "kind": "external",
        "icon": "azure_AzureActiveDirectory__Identity"
      },
      {
        "id": "dbx",
        "label": "Databricks",
        "sub": "governed SQL warehouse",
        "kind": "external"
      },
      {
        "id": "src",
        "label": "Content sources",
        "sub": "read-only",
        "kind": "external"
      }
    ],
    "edges": [
      {
        "from": "fd",
        "to": "apim",
        "label": "TLS 1.3"
      },
      {
        "from": "apim",
        "to": "np1",
        "label": "mTLS"
      },
      {
        "from": "np2",
        "to": "ais",
        "label": "query"
      },
      {
        "from": "ais",
        "to": "ais2",
        "label": "second index build",
        "kind": "batch",
        "route": "gutter"
      },
      {
        "from": "pg",
        "to": "pg2",
        "label": "async replication",
        "kind": "async",
        "route": "gutter"
      }
    ],
    "note": "The secondary is not a copy of the primary: the indexer builds both, so failover does not depend on replicating a search index that Azure AI Search does not replicate for us.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "31-cicd-and-index-migration",
    "title": "CI/CD — Shipping Code, Prompts, Index Schemas and Models Through the Same Gates",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1860
    },
    "stages": [
      {
        "title": "Source",
        "nodes": [
          {
            "id": "s1",
            "label": "Application code",
            "sub": "GitHub, trunk-based"
          },
          {
            "id": "s2",
            "label": "Prompt registry",
            "sub": "versioned, reviewed"
          },
          {
            "id": "s3",
            "label": "Index schema",
            "sub": "declared, migrated"
          },
          {
            "id": "s4",
            "label": "Golden set",
            "sub": "1,400 queries",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Build",
        "nodes": [
          {
            "id": "b1",
            "label": "Container build",
            "sub": "GitHub Actions"
          },
          {
            "id": "b2",
            "label": "SBOM and signature",
            "sub": "Syft and Cosign",
            "kind": "security"
          },
          {
            "id": "b3",
            "label": "Unit and contract tests",
            "sub": "retriever contract"
          }
        ]
      },
      {
        "title": "Evaluate",
        "nodes": [
          {
            "id": "e1",
            "label": "Retrieval metrics",
            "sub": "Recall@50, nDCG@10",
            "kind": "decision"
          },
          {
            "id": "e2",
            "label": "Generation metrics",
            "sub": "groundedness, citations",
            "kind": "decision"
          },
          {
            "id": "e3",
            "label": "Adversarial suite",
            "sub": "injection and leakage",
            "kind": "security"
          },
          {
            "id": "e4",
            "label": "Cost per query",
            "sub": "budget regression",
            "kind": "decision"
          }
        ]
      },
      {
        "title": "Stage",
        "nodes": [
          {
            "id": "t1",
            "label": "Shadow index build",
            "sub": "new alias, not swapped"
          },
          {
            "id": "t2",
            "label": "Shadow traffic",
            "sub": "10% mirrored, not served"
          },
          {
            "id": "t3",
            "label": "Side-by-side scoring",
            "sub": "same queries, both stacks"
          }
        ]
      },
      {
        "title": "Gate",
        "nodes": [
          {
            "id": "g1",
            "label": "Thresholds met",
            "sub": "no metric below baseline",
            "kind": "decision"
          },
          {
            "id": "g2",
            "label": "Human approval",
            "sub": "prompt and policy changes",
            "kind": "security"
          },
          {
            "id": "g3",
            "label": "Change record",
            "sub": "what moved and why",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Release",
        "nodes": [
          {
            "id": "r1",
            "label": "Argo CD sync",
            "sub": "GitOps, per environment",
            "icon": "argocd"
          },
          {
            "id": "r2",
            "label": "Canary 5%",
            "sub": "30 minutes"
          },
          {
            "id": "r3",
            "label": "Alias swap",
            "sub": "index cutover is atomic"
          }
        ]
      },
      {
        "title": "Watch",
        "nodes": [
          {
            "id": "w1",
            "label": "48-hour watch",
            "sub": "online quality signals"
          },
          {
            "id": "w2",
            "label": "Auto rollback",
            "sub": "alias back, pods back",
            "kind": "error"
          },
          {
            "id": "w3",
            "label": "Baseline updated",
            "sub": "new reference scores",
            "kind": "platform"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "w2",
        "to": "s2",
        "label": "revert",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "A prompt change and a code change take the same path. Treating prompts as configuration is how a quality regression reaches production without a review.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "32-evaluation-harness",
    "title": "Evaluation Harness — What Is Measured, Against What, and What It Blocks",
    "layout": "swimlane",
    "canvas": {
      "width": 1860
    },
    "laneHeaderWidth": 200,
    "stages": [
      "Golden set",
      "Measured by",
      "Gate",
      "Runs when"
    ],
    "lanes": [
      {
        "title": "Retrieval",
        "cells": [
          [
            {
              "label": "620 queries, judged pools",
              "sub": "graded 0 to 3",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Recall@50, nDCG@10, MRR",
              "sub": "trec_eval semantics"
            }
          ],
          [
            {
              "label": "Recall@50 at least 0.90",
              "sub": "blocks release",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Every pull request",
              "sub": "fixture corpus"
            }
          ]
        ]
      },
      {
        "title": "Ranking",
        "cells": [
          [
            {
              "label": "Same pools, reranked",
              "sub": "pairwise preferences",
              "kind": "store"
            }
          ],
          [
            {
              "label": "nDCG@10 delta vs fusion",
              "sub": "must be positive"
            }
          ],
          [
            {
              "label": "Gain at least 0.06",
              "sub": "or the reranker is off",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Nightly and on model change",
              "sub": "full corpus"
            }
          ]
        ]
      },
      {
        "title": "Generation",
        "cells": [
          [
            {
              "label": "480 queries with answers",
              "sub": "human-written references",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Groundedness, citation correctness",
              "sub": "Ragas plus NLI judge"
            }
          ],
          [
            {
              "label": "Groundedness at least 0.95",
              "sub": "citations at least 0.97",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Nightly, and every prompt change",
              "sub": "no exceptions"
            }
          ]
        ]
      },
      {
        "title": "End to end",
        "cells": [
          [
            {
              "label": "300 task scenarios",
              "sub": "simple, multi-hop, long-tail",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Task success, abandonment",
              "sub": "and reformulation rate"
            }
          ],
          [
            {
              "label": "Task success at least 0.82",
              "sub": "trend, not a single run",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Nightly, plus weekly online read",
              "sub": "from real traffic"
            }
          ]
        ]
      },
      {
        "title": "Safety and access",
        "cells": [
          [
            {
              "label": "220 adversarial cases",
              "sub": "injection, leakage, PII",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Attack success rate",
              "sub": "and false refusal rate"
            }
          ],
          [
            {
              "label": "Zero access leaks",
              "sub": "a single failure blocks",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Every build, and on new sources",
              "sub": "never sampled"
            }
          ]
        ]
      },
      {
        "title": "Cost and latency",
        "cells": [
          [
            {
              "label": "Traffic-weighted replay",
              "sub": "yesterday's mix",
              "kind": "store"
            }
          ],
          [
            {
              "label": "Cost per answered query, P95",
              "sub": "per class"
            }
          ],
          [
            {
              "label": "Within 10% of baseline",
              "sub": "or approved explicitly",
              "kind": "decision"
            }
          ],
          [
            {
              "label": "Nightly",
              "sub": "reported with quality"
            }
          ]
        ]
      }
    ],
    "note": "Quality and cost are gated together. A change that improves groundedness by two points and doubles the bill is a decision, not an improvement.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "33-ragops-loop",
    "title": "RAGOps — How a Bad Answer Becomes a Fixed System",
    "layout": "cycle",
    "centre": {
      "label": "RAGOps",
      "sub": "weekly cadence"
    },
    "rx": 430,
    "ry": 225,
    "nodes": [
      {
        "id": "o1",
        "label": "Observe",
        "sub": "traces and feedback",
        "kind": "platform"
      },
      {
        "id": "o2",
        "label": "Classify the failure",
        "sub": "which stage broke",
        "kind": "decision"
      },
      {
        "id": "o3",
        "label": "Reproduce",
        "sub": "replay by evidence id"
      },
      {
        "id": "o4",
        "label": "Fix at the stage",
        "sub": "chunking, weights, prompt"
      },
      {
        "id": "o5",
        "label": "Evaluate offline",
        "sub": "against the golden set"
      },
      {
        "id": "o6",
        "label": "Ship behind a flag",
        "sub": "canary, then all"
      },
      {
        "id": "o7",
        "label": "Promote to golden",
        "sub": "the case becomes a test",
        "kind": "store"
      }
    ],
    "ringLabels": [
      "a wrong answer, with its trace",
      "retrieval, rank, context or model",
      "the exact evidence set returns",
      "one change, one stage",
      "gate passes or the fix is wrong",
      "measured online for 48 hours",
      "it can never regress silently"
    ],
    "note": "The loop closes only when the failing query joins the golden set. A fix that is not testable tomorrow is a patch, not an improvement.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "34-observability-and-tracing",
    "title": "Observability — One Trace That Answers Which Stage Was Wrong",
    "layout": "grid",
    "canvas": {
      "width": 1860
    },
    "laneHeaderWidth": 210,
    "columns": [
      "Span recorded",
      "Metric",
      "What it proves",
      "Alerts when"
    ],
    "rows": [
      {
        "title": "Query understanding",
        "cells": [
          [
            {
              "label": "class, entities, rewrite",
              "sub": "and confidence"
            }
          ],
          [
            {
              "label": "class distribution",
              "sub": "vs the 7-day baseline"
            }
          ],
          [
            {
              "label": "The question was read correctly",
              "sub": "or was not"
            }
          ],
          [
            {
              "label": "class mix shifts 20%",
              "sub": "usually a UI change",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Authorisation",
        "cells": [
          [
            {
              "label": "group set size, fingerprint",
              "sub": "never the group names",
              "kind": "security"
            }
          ],
          [
            {
              "label": "expansion latency P95",
              "sub": "and cache hit rate"
            }
          ],
          [
            {
              "label": "The filter was applied",
              "sub": "and to what"
            }
          ],
          [
            {
              "label": "any query without a filter",
              "sub": "page immediately",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Retrieval",
        "cells": [
          [
            {
              "label": "per backend: query, depth, latency",
              "sub": "and every id returned"
            }
          ],
          [
            {
              "label": "recall proxy, zero-result rate",
              "sub": "per source"
            }
          ],
          [
            {
              "label": "The right document was found",
              "sub": "or never was"
            }
          ],
          [
            {
              "label": "zero-result rate above 4%",
              "sub": "per source",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Ranking",
        "cells": [
          [
            {
              "label": "fusion order, rerank scores",
              "sub": "before and after"
            }
          ],
          [
            {
              "label": "rank of the cited passage",
              "sub": "distribution",
              "icon": "fa5_sort"
            }
          ],
          [
            {
              "label": "It was found and then buried",
              "sub": "the commonest cause"
            }
          ],
          [
            {
              "label": "cited rank drifts past 6",
              "sub": "ranking regression",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Context assembly",
        "cells": [
          [
            {
              "label": "slots, tokens, what was dropped",
              "sub": "and why"
            }
          ],
          [
            {
              "label": "evidence truncation rate"
            }
          ],
          [
            {
              "label": "The model was given enough",
              "sub": "or was starved"
            }
          ],
          [
            {
              "label": "truncation above 8%",
              "sub": "budget is wrong",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Model call",
        "cells": [
          [
            {
              "label": "model, tokens, cost, retries",
              "sub": "prompt version"
            }
          ],
          [
            {
              "label": "TTFT, total latency, spend"
            }
          ],
          [
            {
              "label": "It had what it needed and still failed",
              "sub": "a model problem"
            }
          ],
          [
            {
              "label": "TTFT P95 above 2.5 s",
              "sub": "or spend above budget",
              "kind": "risk"
            }
          ]
        ]
      },
      {
        "title": "Verification and answer",
        "cells": [
          [
            {
              "label": "claims, verdicts, citations",
              "sub": "abstentions recorded",
              "kind": "store"
            }
          ],
          [
            {
              "label": "groundedness, abstain rate",
              "sub": "and feedback"
            }
          ],
          [
            {
              "label": "What the user was actually shown"
            }
          ],
          [
            {
              "label": "abstain rate above 6%",
              "sub": "corpus gap, not a bug",
              "kind": "risk"
            }
          ]
        ]
      }
    ],
    "note": "One trace id spans all seven rows. Without it, every quality question becomes an argument between the retrieval team and the model team.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "35-cost-model",
    "title": "Cost Model — What a Query Costs and Which Levers Move It",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1800
    },
    "stages": [
      {
        "title": "Demand",
        "nodes": [
          {
            "id": "q1",
            "label": "62,000 queries a day",
            "sub": "peak 34 per second"
          },
          {
            "id": "q2",
            "label": "Class mix from view 04",
            "sub": "11% agentic"
          },
          {
            "id": "q3",
            "label": "40 M documents",
            "sub": "320 M chunks",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Where money goes",
        "nodes": [
          {
            "id": "m1",
            "label": "LLM tokens",
            "sub": "58% of run cost",
            "icon": "fa5_coins"
          },
          {
            "id": "m2",
            "label": "GPU node pools",
            "sub": "19%",
            "icon": "fa5_microchip"
          },
          {
            "id": "m3",
            "label": "Azure AI Search",
            "sub": "14%",
            "icon": "azure_search"
          },
          {
            "id": "m4",
            "label": "Storage, egress, ops",
            "sub": "9%",
            "icon": "fa5_hdd"
          }
        ]
      },
      {
        "title": "What each scales with",
        "nodes": [
          {
            "id": "d1",
            "label": "Tokens: class mix and hops",
            "sub": "not user count",
            "icon": "fa5_coins"
          },
          {
            "id": "d2",
            "label": "GPU: queries per second",
            "sub": "plus reindex bursts",
            "icon": "fa5_microchip"
          },
          {
            "id": "d3",
            "label": "Search: chunk count",
            "sub": "and replica count",
            "icon": "azure_search"
          }
        ]
      },
      {
        "title": "Levers",
        "nodes": [
          {
            "id": "l1",
            "label": "Semantic cache",
            "sub": "35% hit, 0 tokens",
            "icon": "azure_cache-redis"
          },
          {
            "id": "l2",
            "label": "Class routing",
            "sub": "the largest single saving"
          },
          {
            "id": "l3",
            "label": "Rerank depth 50",
            "sub": "not 200"
          },
          {
            "id": "l4",
            "label": "Spot GPU for batch embed",
            "sub": "62% cheaper"
          }
        ]
      },
      {
        "title": "Guardrails",
        "nodes": [
          {
            "id": "gr1",
            "label": "Budget governor",
            "sub": "per query, hard stop",
            "kind": "decision",
            "icon": "fa5_coins"
          },
          {
            "id": "gr2",
            "label": "Per-tenant quota",
            "sub": "daily token ceiling",
            "kind": "security"
          },
          {
            "id": "gr3",
            "label": "Cost in the eval gate",
            "sub": "view 32",
            "kind": "platform"
          }
        ]
      },
      {
        "title": "Outcome",
        "nodes": [
          {
            "id": "o1",
            "label": "0.021 USD blended",
            "sub": "per answered query"
          },
          {
            "id": "o2",
            "label": "0.004 USD lookup",
            "sub": "0.180 USD agentic"
          },
          {
            "id": "o3",
            "label": "About 39k USD a month",
            "sub": "at current volume"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "l1",
        "to": "m1",
        "label": "removes the token line",
        "kind": "batch",
        "route": "gutter"
      }
    ],
    "note": "The agentic class is 45 times the cost of a lookup. Routing, not model choice, is what keeps the blended figure where it is.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "36-security-zones",
    "title": "Security Zones — Trust Boundaries and What Crosses Them",
    "layout": "zones",
    "canvas": {
      "width": 1840
    },
    "zones": [
      {
        "title": "Internet",
        "kind": "trust",
        "nodes": [
          {
            "id": "br",
            "label": "Browser and mobile",
            "sub": "managed devices",
            "kind": "external"
          },
          {
            "id": "pub",
            "label": "Public web sources",
            "sub": "crawled, untrusted",
            "kind": "external"
          },
          {
            "id": "atk",
            "label": "Attacker",
            "sub": "or a poisoned document",
            "kind": "risk"
          }
        ]
      },
      {
        "title": "Edge",
        "kind": "trust",
        "nodes": [
          {
            "id": "fd",
            "label": "Front Door and WAF",
            "sub": "TLS 1.3, bot rules",
            "kind": "security"
          },
          {
            "id": "apim",
            "label": "API Management",
            "sub": "token validation, quota",
            "kind": "integration"
          },
          {
            "id": "ddos",
            "label": "DDoS protection",
            "sub": "standard tier",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Application",
        "kind": "trust",
        "nodes": [
          {
            "id": "gw",
            "label": "Search Gateway",
            "sub": "no source credentials"
          },
          {
            "id": "pl",
            "label": "Planner and retrieval",
            "sub": "acts as the caller"
          },
          {
            "id": "pol",
            "label": "Policy Engine",
            "sub": "OPA, decisions logged",
            "kind": "security"
          },
          {
            "id": "tb",
            "label": "Tool Broker",
            "sub": "egress allowlist",
            "kind": "security",
            "icon": "fa5_toolbox"
          }
        ]
      },
      {
        "title": "Model and GPU",
        "kind": "trust",
        "nodes": [
          {
            "id": "vllm",
            "label": "Self-hosted models",
            "sub": "no egress, no internet"
          },
          {
            "id": "aoai",
            "label": "Azure OpenAI",
            "sub": "private endpoint",
            "kind": "external",
            "icon": "azure_openai"
          },
          {
            "id": "acs",
            "label": "Content Safety",
            "sub": "screens both directions",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Data",
        "kind": "trust",
        "nodes": [
          {
            "id": "ais",
            "label": "Azure AI Search",
            "sub": "private endpoint only",
            "kind": "store",
            "icon": "azure_search"
          },
          {
            "id": "pg",
            "label": "PostgreSQL",
            "sub": "CMK, no public route",
            "kind": "store"
          },
          {
            "id": "st",
            "label": "ADLS Gen2",
            "sub": "immutable raw",
            "kind": "store"
          },
          {
            "id": "kv",
            "label": "Key Vault",
            "sub": "workload identity only",
            "kind": "security"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "br",
        "to": "fd",
        "label": "HTTPS, Entra token"
      },
      {
        "from": "fd",
        "to": "gw",
        "label": "private link"
      },
      {
        "from": "gw",
        "to": "ais",
        "label": "filtered query"
      },
      {
        "from": "pl",
        "to": "aoai",
        "label": "fenced context"
      },
      {
        "from": "pub",
        "to": "st",
        "label": "crawled, screened",
        "kind": "batch"
      },
      {
        "from": "atk",
        "to": "pl",
        "label": "injection attempt",
        "kind": "error"
      },
      {
        "from": "tb",
        "to": "kv",
        "label": "short-lived credential"
      }
    ],
    "note": "The only inbound path is Front Door. Every data service refuses public traffic, and no application pod holds a long-lived secret.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "37-identity-and-authorisation",
    "title": "Identity and Authorisation — Who Proves What, to Whom, in What Order",
    "layout": "sequence",
    "canvas": {
      "width": 1780
    },
    "lifelines": [
      {
        "id": "u",
        "label": "User",
        "kind": "actor"
      },
      {
        "id": "app",
        "label": "Client App"
      },
      {
        "id": "aad",
        "label": "Entra ID",
        "kind": "security",
        "icon": "azure_AzureActiveDirectory__Identity"
      },
      {
        "id": "apim",
        "label": "API Management",
        "kind": "integration"
      },
      {
        "id": "gw",
        "label": "Search Gateway"
      },
      {
        "id": "er",
        "label": "Entitlement Resolver",
        "kind": "security",
        "icon": "fa5_user_shield"
      },
      {
        "id": "ix",
        "label": "Azure AI Search",
        "kind": "store",
        "icon": "azure_search"
      },
      {
        "id": "au",
        "label": "Audit Log",
        "kind": "store"
      }
    ],
    "messages": [
      {
        "from": "u",
        "to": "app",
        "label": "opens search",
        "kind": "call"
      },
      {
        "from": "app",
        "to": "aad",
        "label": "authorisation code with PKCE",
        "kind": "call"
      },
      {
        "from": "aad",
        "to": "app",
        "label": "access token, 60 min",
        "kind": "return"
      },
      {
        "from": "app",
        "to": "apim",
        "label": "POST /v1/answer with the user token",
        "kind": "call"
      },
      {
        "from": "apim",
        "to": "apim",
        "label": "validate signature, audience, quota",
        "kind": "self"
      },
      {
        "from": "apim",
        "to": "gw",
        "label": "forwarded with the caller identity",
        "kind": "call"
      },
      {
        "from": "gw",
        "to": "aad",
        "label": "on-behalf-of exchange",
        "kind": "call"
      },
      {
        "from": "aad",
        "to": "gw",
        "label": "downstream token for Graph",
        "kind": "return"
      },
      {
        "from": "gw",
        "to": "er",
        "label": "resolve entitlements",
        "kind": "call"
      },
      {
        "from": "er",
        "to": "aad",
        "label": "transitive group membership",
        "kind": "call"
      },
      {
        "from": "aad",
        "to": "er",
        "label": "object ids, cached 60 s",
        "kind": "return"
      },
      {
        "from": "er",
        "to": "gw",
        "label": "group set and ACL fingerprint",
        "kind": "return"
      },
      {
        "from": "gw",
        "to": "ix",
        "label": "query with acl filter and classification ceiling",
        "kind": "call"
      },
      {
        "from": "ix",
        "to": "gw",
        "label": "only permitted chunks",
        "kind": "return"
      },
      {
        "from": "gw",
        "to": "au",
        "label": "principal, query, evidence ids",
        "kind": "async"
      },
      {
        "from": "gw",
        "to": "u",
        "label": "answer the caller was entitled to",
        "kind": "return"
      }
    ],
    "note": "There is no service identity that can read content on a user's behalf. If the on-behalf-of exchange fails, the request fails; it never falls back to an application identity.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "38-untrusted-content-defence",
    "title": "Untrusted Content — Six Attacks and What Stops Each",
    "layout": "grid",
    "canvas": {
      "width": 1860
    },
    "laneHeaderWidth": 220,
    "columns": [
      "Where it enters",
      "What it attempts",
      "Control",
      "Residual risk"
    ],
    "rows": [
      {
        "title": "Instruction inside a document",
        "cells": [
          [
            {
              "label": "Any indexed source",
              "sub": "white text, alt text, notes"
            }
          ],
          [
            {
              "label": "Be obeyed as a system rule",
              "sub": "ignore prior instructions",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Fenced evidence slot",
              "sub": "plus screening at index",
              "kind": "security"
            }
          ],
          [
            {
              "label": "Novel phrasings evade detection",
              "sub": "the fence still holds"
            }
          ]
        ]
      },
      {
        "title": "Poisoned public page",
        "cells": [
          [
            {
              "label": "Crawled web source",
              "sub": "40 allowed domains"
            }
          ],
          [
            {
              "label": "Rank above internal policy",
              "sub": "and be cited",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Authority weight, source policy",
              "sub": "external never outranks internal",
              "kind": "security"
            }
          ],
          [
            {
              "label": "A legitimate external page can still mislead",
              "sub": "citation makes it visible"
            }
          ]
        ]
      },
      {
        "title": "Malicious tool argument",
        "cells": [
          [
            {
              "label": "Model output after reading a document"
            }
          ],
          [
            {
              "label": "Reach a system or exfiltrate",
              "sub": "arbitrary SQL or URL",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Broker allowlist, compiled SQL",
              "sub": "no free-form statements",
              "kind": "security"
            }
          ],
          [
            {
              "label": "An allowlisted tool misused within its scope",
              "sub": "audited per call"
            }
          ]
        ]
      },
      {
        "title": "Exfiltration via a link",
        "cells": [
          [
            {
              "label": "Answer rendering",
              "sub": "markdown image or link"
            }
          ],
          [
            {
              "label": "Send context to an outside host",
              "sub": "as a URL parameter",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Links only to cited sources",
              "sub": "no model-authored URLs",
              "kind": "security"
            }
          ],
          [
            {
              "label": "None known; the renderer is the control"
            }
          ]
        ]
      },
      {
        "title": "Scope escalation by asking",
        "cells": [
          [
            {
              "label": "The user turn itself"
            }
          ],
          [
            {
              "label": "Retrieve what the caller may not open",
              "sub": "act as another principal",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Filter is server-composed",
              "sub": "the query cannot set it",
              "kind": "security",
              "icon": "fa5_shield_alt"
            }
          ],
          [
            {
              "label": "Inference from the absence of results",
              "sub": "accepted and documented"
            }
          ]
        ]
      },
      {
        "title": "Jailbreak in the user turn",
        "cells": [
          [
            {
              "label": "The user turn itself"
            }
          ],
          [
            {
              "label": "Bypass safety or the answer format",
              "kind": "risk"
            }
          ],
          [
            {
              "label": "Prompt Shields plus schema validation",
              "sub": "output must parse",
              "kind": "security"
            }
          ],
          [
            {
              "label": "Over-refusal annoys real users",
              "sub": "false refusal rate is a gate"
            }
          ]
        ]
      }
    ],
    "note": "The controls are structural, not lexical. A filter that looks for the phrase ignore previous instructions has already lost; the evidence slot is never read as instruction in the first place.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "39-sensitive-data-and-isolation",
    "title": "Sensitive Data and Tenant Isolation",
    "layout": "nested",
    "canvas": {
      "width": 1840
    },
    "boxes": [
      {
        "title": "Detected once, at ingest",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Detectors",
            "kind": "plain",
            "nodes": [
              {
                "label": "Presidio recognisers",
                "sub": "names, ids, accounts",
                "kind": "security"
              },
              {
                "label": "Purview label read",
                "sub": "authored by the business",
                "kind": "security"
              },
              {
                "label": "Internal identifier patterns",
                "sub": "curated regexes",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Written to the chunk",
            "kind": "plain",
            "nodes": [
              {
                "label": "classification",
                "sub": "public to restricted",
                "kind": "store",
                "icon": "fa5_tags"
              },
              {
                "label": "pii_kinds[]",
                "sub": "for redaction rules",
                "kind": "store"
              }
            ]
          }
        ]
      },
      {
        "title": "Enforced at retrieval and display",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Retrieval",
            "kind": "plain",
            "nodes": [
              {
                "label": "Classification ceiling per request",
                "sub": "from the caller, not the query",
                "kind": "security"
              },
              {
                "label": "Restricted sources excluded",
                "sub": "unless the class allows them",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Display",
            "kind": "plain",
            "nodes": [
              {
                "label": "Redaction at render",
                "sub": "never in the index",
                "kind": "security"
              },
              {
                "label": "Reveal is an audited action",
                "sub": "with a reason",
                "kind": "store"
              }
            ]
          }
        ]
      },
      {
        "title": "Constrained in generation",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "Model handling",
            "kind": "plain",
            "nodes": [
              {
                "label": "No tenant data in prompts to shared models",
                "sub": "beyond the evidence slot",
                "kind": "security"
              },
              {
                "label": "No training or fine-tuning on content",
                "sub": "contractual and technical",
                "kind": "security"
              },
              {
                "label": "Abuse-monitoring retention disabled",
                "sub": "approved exemption",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Logging",
            "kind": "plain",
            "nodes": [
              {
                "label": "Traces store ids, not text",
                "sub": "passages by reference",
                "kind": "store"
              },
              {
                "label": "Prompt capture is opt-in",
                "sub": "and time-boxed",
                "kind": "decision"
              }
            ]
          }
        ]
      },
      {
        "title": "Isolation between business units and regions",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "Boundaries",
            "kind": "plain",
            "nodes": [
              {
                "label": "tenant field on every chunk",
                "sub": "filter, never a convention",
                "kind": "security"
              },
              {
                "label": "Separate index for regulated units",
                "sub": "physical, not logical",
                "kind": "security"
              },
              {
                "label": "Customer-managed keys per unit",
                "sub": "revocable",
                "kind": "security"
              }
            ]
          },
          {
            "title": "Subject rights",
            "kind": "plain",
            "nodes": [
              {
                "label": "Erasure removes chunks and traces",
                "sub": "within 30 days",
                "kind": "decision"
              },
              {
                "label": "Provenance keeps the reference",
                "sub": "not the content",
                "kind": "store"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "label": "Source systems remain the record for a subject access request",
        "kind": "external"
      }
    ],
    "note": "Classification is decided once, at ingest, and enforced everywhere afterwards by a filter. Deciding it at query time would make every new consumer a new security review.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "40-governance-and-audit",
    "title": "Governance and Audit — From a Written Policy to Evidence an Auditor Accepts",
    "layout": "flow",
    "chain": true,
    "align": "top",
    "canvas": {
      "width": 1800
    },
    "stages": [
      {
        "title": "Policy",
        "nodes": [
          {
            "id": "p1",
            "label": "Source policy",
            "sub": "who may index what",
            "kind": "security"
          },
          {
            "id": "p2",
            "label": "Model policy",
            "sub": "which models, which data",
            "kind": "security"
          },
          {
            "id": "p3",
            "label": "Tool policy",
            "sub": "per query class",
            "kind": "security"
          },
          {
            "id": "p4",
            "label": "Retention policy",
            "sub": "traces, answers, feedback",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Expressed as",
        "nodes": [
          {
            "id": "x1",
            "label": "OPA rules in git",
            "sub": "reviewed, versioned"
          },
          {
            "id": "x2",
            "label": "Index schema fields",
            "sub": "classification, tenant"
          },
          {
            "id": "x3",
            "label": "Gateway configuration",
            "sub": "model routing, budgets"
          }
        ]
      },
      {
        "title": "Enforced at",
        "nodes": [
          {
            "id": "e1",
            "label": "Index-side filter",
            "sub": "before scoring",
            "kind": "security"
          },
          {
            "id": "e2",
            "label": "Model Gateway",
            "sub": "model and region choice",
            "kind": "security"
          },
          {
            "id": "e3",
            "label": "Tool Broker",
            "sub": "call-by-call",
            "kind": "security",
            "icon": "fa5_toolbox"
          },
          {
            "id": "e4",
            "label": "Verifier",
            "sub": "what may be shown",
            "kind": "security",
            "icon": "fa5_check_double"
          }
        ]
      },
      {
        "title": "Recorded as",
        "nodes": [
          {
            "id": "r1",
            "label": "Audit log",
            "sub": "append-only, 7 years",
            "kind": "store"
          },
          {
            "id": "r2",
            "label": "Answer provenance",
            "sub": "claims and evidence ids",
            "kind": "store"
          },
          {
            "id": "r3",
            "label": "Decision log",
            "sub": "every policy evaluation",
            "kind": "store"
          },
          {
            "id": "r4",
            "label": "Evaluation history",
            "sub": "every gate, every release",
            "kind": "store"
          }
        ]
      },
      {
        "title": "Reviewed by",
        "nodes": [
          {
            "id": "v1",
            "label": "Source onboarding review",
            "sub": "before a source is indexed"
          },
          {
            "id": "v2",
            "label": "Quarterly architecture board",
            "sub": "policy and drift"
          },
          {
            "id": "v3",
            "label": "Red team",
            "sub": "twice a year",
            "kind": "security"
          }
        ]
      },
      {
        "title": "Evidence produced",
        "nodes": [
          {
            "id": "a1",
            "label": "Replay any answer",
            "sub": "from its evidence ids"
          },
          {
            "id": "a2",
            "label": "Prove entitlement at the time",
            "sub": "fingerprint plus ACL history"
          },
          {
            "id": "a3",
            "label": "Show the quality record",
            "sub": "gates at that release"
          }
        ]
      }
    ],
    "edges": [
      {
        "from": "v3",
        "to": "p3",
        "label": "findings change policy",
        "kind": "error",
        "route": "gutter"
      }
    ],
    "note": "Explainability here means naming the evidence that produced an answer, not interpreting the model. That is answerable; the other is not.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  },
  {
    "id": "41-failure-modes",
    "title": "Failure Modes — Named, Detected and Answered",
    "layout": "nested",
    "canvas": {
      "width": 1860
    },
    "boxes": [
      {
        "title": "Retrieval — the answer was wrong before the model saw anything",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "How it fails",
            "kind": "plain",
            "nodes": [
              {
                "label": "Document never indexed",
                "sub": "parse failed silently",
                "kind": "risk"
              },
              {
                "label": "Entitlement stale",
                "sub": "index behind the source",
                "kind": "risk"
              },
              {
                "label": "Answer split across chunks",
                "sub": "neither is retrievable",
                "kind": "risk"
              },
              {
                "label": "Embedding drift",
                "sub": "two model versions live",
                "kind": "risk"
              }
            ]
          },
          {
            "title": "Detected and answered by",
            "kind": "plain",
            "nodes": [
              {
                "label": "Per-document receipt",
                "sub": "steward console, view 08",
                "kind": "platform"
              },
              {
                "label": "60-second ACL delta",
                "sub": "plus cache invalidation",
                "kind": "platform"
              },
              {
                "label": "Structure-aware chunking",
                "sub": "and coverage probes",
                "kind": "platform"
              },
              {
                "label": "Alias cutover, never mixed",
                "sub": "view 31",
                "kind": "platform"
              }
            ]
          }
        ]
      },
      {
        "title": "Generation — the evidence was right and the answer was not",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "How it fails",
            "kind": "plain",
            "nodes": [
              {
                "label": "Unsupported claim",
                "sub": "fluent and wrong",
                "kind": "risk"
              },
              {
                "label": "Contradiction smoothed",
                "sub": "false consensus",
                "kind": "risk"
              },
              {
                "label": "Over-refusal",
                "sub": "abstains on a good answer",
                "kind": "risk"
              },
              {
                "label": "Schema break",
                "sub": "citations unparseable",
                "kind": "risk"
              }
            ]
          },
          {
            "title": "Detected and answered by",
            "kind": "plain",
            "nodes": [
              {
                "label": "Claim-level NLI",
                "sub": "drop or re-retrieve",
                "kind": "platform"
              },
              {
                "label": "Contradiction detector",
                "sub": "both positions shown",
                "kind": "platform"
              },
              {
                "label": "False refusal rate gate",
                "sub": "view 32",
                "kind": "platform"
              },
              {
                "label": "Validate and retry once",
                "sub": "then fall back",
                "kind": "platform"
              }
            ]
          }
        ]
      },
      {
        "title": "Security — the boundary held, or it did not",
        "kind": "trust",
        "dir": "row",
        "children": [
          {
            "title": "How it fails",
            "kind": "plain",
            "nodes": [
              {
                "label": "Cross-principal cache hit",
                "sub": "the highest-severity bug",
                "kind": "risk"
              },
              {
                "label": "Injection reaches a tool",
                "sub": "document as instruction",
                "kind": "risk"
              },
              {
                "label": "Prompt log holds content",
                "sub": "logging becomes a copy",
                "kind": "risk"
              }
            ]
          },
          {
            "title": "Detected and answered by",
            "kind": "plain",
            "nodes": [
              {
                "label": "Fingerprint in every key",
                "sub": "plus a nightly assertion",
                "kind": "platform"
              },
              {
                "label": "Broker provenance check",
                "sub": "and egress allowlist",
                "kind": "platform"
              },
              {
                "label": "Traces store ids only",
                "sub": "capture is opt-in",
                "kind": "platform"
              }
            ]
          }
        ]
      },
      {
        "title": "Operations — it worked yesterday",
        "kind": "boundary",
        "dir": "row",
        "children": [
          {
            "title": "How it fails",
            "kind": "plain",
            "nodes": [
              {
                "label": "GPU pool exhausted",
                "sub": "reindex meets peak",
                "kind": "risk"
              },
              {
                "label": "Source throttles the connector",
                "sub": "freshness silently slips",
                "kind": "risk"
              },
              {
                "label": "Cost runaway",
                "sub": "one agentic loop pattern",
                "kind": "risk"
              },
              {
                "label": "Model deprecated by the provider",
                "sub": "with notice, still disruptive",
                "kind": "risk"
              }
            ]
          },
          {
            "title": "Detected and answered by",
            "kind": "plain",
            "nodes": [
              {
                "label": "Separate pools and priorities",
                "sub": "batch is preemptible",
                "kind": "platform"
              },
              {
                "label": "Freshness SLO per source",
                "sub": "staleness is published",
                "kind": "platform"
              },
              {
                "label": "Budget governor and quota",
                "sub": "hard stop per query",
                "kind": "platform",
                "icon": "fa5_coins"
              },
              {
                "label": "Gateway abstraction",
                "sub": "swap and re-evaluate",
                "kind": "platform"
              }
            ]
          }
        ]
      }
    ],
    "outside": [
      {
        "label": "Accepted risk — a correct answer from a stale but authorised document",
        "sub": "answered by publishing as-of, not by blocking",
        "kind": "risk"
      }
    ],
    "note": "Every failure here is named, has a detector and has an owner. A failure mode with no detector is the one that becomes an incident.",
    "meta": {
      "v": "1.0",
      "owner": "Data and AI Global Practice"
    }
  }
]
