flowchart TD
    A["HTTP: POST /internal/rag/retrieve"] --> B["RagModule.internal_router.retrieve(payload)"]
    B --> C["RagService.retrieve(rag_session_id, query)"]
    C --> D["RagQueryRouter.resolve_mode(query)"]
    D --> E["RagQueryRouter.layers_for_mode(mode)"]
    C --> F["GigaChatEmbedder.embed([query])"]
    F --> G["GigaChatClient.embed(payload)"]
    G --> H["POST /embeddings"]
    C --> I["RagRepository.retrieve(...)"]
    I --> J["RagQueryRepository.retrieve(...)"]
    J --> K["PostgreSQL rag_chunks + pgvector"]
    K --> L["ORDER BY lexical_rank, test_penalty, layer_rank, vector distance"]
    L --> M["rows: path/content/layer/title/metadata/span/distance"]
    M --> N["normalize to {source, content, layer, title, metadata, score}"]
    N --> O["response: {items: [...]}"]

    C --> P["embedding error?"]
    P -->|yes| Q["RagRepository.fallback_chunks(...)"]
    Q --> R["latest rows by id DESC"]
    R --> N

    C --> S["no rows and mode != docs?"]
    S -->|yes| T["fallback to docs layers"]
    T --> I

    U["GraphAgentRuntime for project/qa"] --> V["ProjectQaRetrievalGraphFactory._retrieve_context"]
    V --> C
    V --> W["ProjectQaSupport.build_source_bundle(...)"]
    W --> X["source_bundle"]
    X --> Y["context_analysis"]
    Y --> Z["answer_composition"]
