flowchart TD
    Start["LSP request for .sql file"] --> Kind{"Request kind"}
    Kind -->|"completion"| Completion["CompletionService.complete_sql"]
    Completion --> ContextA["SqlFileContext.from_path resolves Quality Spec and Dataset"]
    ContextA --> InJinja{"cursor_in_jinja_block is true"}
    InJinja -->|"yes"| JinjaCompletions["jinja_completions returns built-ins plus columns"]
    InJinja -->|"no"| PlainCompletions["sql_plain_completions returns columns plus SQL keywords"]
    JinjaCompletions --> AssertCompletion["Tests assert this, since, until present and pk, filter absent"]
    PlainCompletions --> AssertPlainCompletion["Tests assert plain SQL completions stay column and keyword scoped"]

    Kind -->|"hover"| Hover["HoverService.hover_sql"]
    Hover --> ContextB["SqlFileContext.from_path resolves Quality Spec and Dataset"]
    ContextB --> JinjaHover{"cursor over Jinja variable"}
    JinjaHover -->|"this"| ThisDoc["doc includes resolved Dataset table"]
    JinjaHover -->|"since or until"| TimeDoc["doc explains ISO datetime string and None when flag absent"]
    JinjaHover -->|"pk or filter"| NoDoc["returns None"]
sequenceDiagram
    participant Test as pytest
    participant Completion as CompletionService
    participant Hover as HoverService
    participant Context as SqlFileContext
    participant Index as ProjectIndex
    participant Core as Jinja helpers

    Test->>Completion: complete SQL query at "{{ "
    Completion->>Context: from_path(sql_path, index)
    Context->>Index: contracts and find_contract
    Index-->>Context: Quality Spec and target Dataset
    Context-->>Completion: SqlFileContext
    Completion->>Core: jinja_completions
    Core-->>Completion: CompletionItemInfo for this since until
    Completion-->>Test: tuple of completion items

    Test->>Hover: hover SQL query at "{{ this }}"
    Hover->>Context: from_path(sql_path, index)
    Context-->>Hover: SqlFileContext
    Hover->>Core: resolve_jinja_hover
    Core-->>Hover: HoverInfo or None
    Hover-->>Test: markdown documentation
classDiagram
    class CompletionService {
        +complete(query) tuple~CompletionItemInfo~
        +complete_sql(query) tuple~CompletionItemInfo~
    }

    class CompletionQuery {
        +str uri
        +str content
        +int line
        +int col
    }

    class CompletionItemInfo {
        +str label
        +CompletionKind kind
        +str detail
        +str documentation
    }

    class HoverService {
        +hover(query, sink) HoverInfo
        +hover_sql(query) HoverInfo
    }

    class HoverQuery {
        +str uri
        +str content
        +int line
        +int col
    }

    class HoverInfo {
        +str content
    }

    class SqlFileContext {
        +Path quality_spec_path
        +str target_contract_id
        +str dataset
        +tuple~ColumnDef~ columns
        +dict~str_str~ params
        +from_path(sql_path, index) SqlFileContext
    }

    class ProjectIndex {
        +contracts() tuple~DatasetSpec~
        +find_contract(contract_id) DatasetSpec
    }

    CompletionService --> CompletionQuery
    CompletionService --> CompletionItemInfo
    CompletionService --> SqlFileContext
    HoverService --> HoverQuery
    HoverService --> HoverInfo
    HoverService --> SqlFileContext
    SqlFileContext --> ProjectIndex