flowchart TD
    REQ["LSP completion request"] --> SVC["CompletionService.complete"]
    SVC --> ROUTE{"URI router"}
    ROUTE -- "empty" --> SCAF["scaffolds_for_uri"]
    ROUTE -- ".sql" --> SQL["complete_sql: Jinja or SQL keywords"]
    ROUTE -- ".yaml" --> YAML["complete_yaml"]
    ROUTE -- "other" --> EMPTY1["return ()"]
    YAML --> REPAIR["repair.parse_or_repair (single pass)"]
    REPAIR -- "fail" --> EMPTY2["return ()"]
    REPAIR -- "ok" --> CAN{"schema_resolver.can_resolve"}
    CAN -- "false" --> EMPTY3["return ()"]
    CAN -- "true" --> ROLE["detect_role (line text, col)"]
    ROLE --> PATH["resolve_dotted_path (tree port plus source map)"]
    PATH --> TGT["target_at (priority 1 to 7)"]
    TGT --> CTX["build CompletionContext"]
    CTX --> DISPATCH["dispatch.complete (role, target, ctx)"]
    DISPATCH --> ARM{"match arm"}
    ARM -- "Key or Empty, ObjectShape" --> OK["completers.object_keys.complete"]
    ARM -- "DashItem or Empty, ArrayOfObjects" --> AOO["completers.array_items.complete_object_item"]
    ARM -- "DashItem or Empty, ArrayOfScalars" --> AOS["completers.array_items.complete_scalar_item"]
    ARM -- "Value, Scalar" --> SV["completers.scalar_value.complete"]
    ARM -- "Value, ColumnRef" --> RC["completers.refs.complete_column"]
    ARM -- "Value, DbTable" --> DT["completers.db.complete_table"]
    ARM -- "Value, DbColumn" --> DC["completers.db.complete_column"]
    ARM -- "Value, DomainRef" --> RD["completers.refs.complete_domain"]
    ARM -- "Value, ContractRef" --> RR["completers.refs.complete_contract"]
    ARM -- "Value, DatasetRef" --> RDS["completers.refs.complete_dataset"]
    ARM -- "Value, SqlCheckRef" --> RS["completers.refs.complete_sql_check"]
    ARM -- "catch all NotInSchema or impossible" --> EMPTY4["return ()"]
    OK --> ITEMS["tuple of CompletionItemInfo"]
    AOO --> ITEMS
    AOS --> ITEMS
    SV --> ITEMS
    RC --> ITEMS
    DT --> ITEMS
    DC --> ITEMS
    RD --> ITEMS
    RR --> ITEMS
    RDS --> ITEMS
    RS --> ITEMS
sequenceDiagram
    participant H as LSP handler
    participant S as CompletionService
    participant R as repair.parse_or_repair
    participant DR as detect_role
    participant TA as target_at
    participant D as dispatch.complete
    participant C as completer arm
    participant SR as SchemaResolver port
    participant IC as IntrospectionCache port
    H->>S: complete(query)
    S->>S: route by URI (empty, .sql, .yaml)
    S->>R: parse_or_repair(parser, query)
    R-->>S: RawSource or None
    S->>SR: can_resolve(data)
    SR-->>S: True
    S->>DR: detect_role(line_text, col)
    DR-->>S: CursorRole value
    S->>S: resolve_dotted_path via tree port and source map
    S->>TA: target_at(data, path, resolver, index, intro, registry, checks_dir)
    TA->>SR: turbine_ref_at(data, path)
    SR-->>TA: extension dict or None
    TA->>SR: resolve_children(data, path)
    SR-->>TA: ResolvedNode
    TA-->>S: CompletionTarget variant
    S->>S: build CompletionContext
    S->>D: complete(role, target, ctx)
    D->>C: arm(target, ctx)
    C->>SR: resolve_children when needed
    C->>IC: known_table_names or get_table when needed
    C-->>D: tuple of CompletionItemInfo
    D-->>S: items
    S-->>H: items
classDiagram
    class CompletionService {
        +parser: Callable
        +schema_resolver: SchemaResolver
        +tree_port: DocumentTreePort
        +index_provider: Callable
        +introspection_provider: Callable
        +checks_dir: Path
        +layout: ProjectLayout
        +domain_registry: DomainRegistry
        +complete(query) tuple~CompletionItemInfo~
    }
    class CompletionContext {
        <<dataclass>>
        +data: dict
        +path: str
        +source_map: SourceMap
        +schema_resolver: SchemaResolver
        +index: ProjectIndex
        +introspection: IntrospectionCache
        +domain_registry: DomainRegistry
        +checks_dir: Path
    }
    class CursorRole {
        <<StrEnum>>
        KEY
        VALUE
        DASH_ITEM
        EMPTY
    }
    class CompletionTarget {
        <<union>>
    }
    class ObjectShape
    class ArrayOfObjects
    class ArrayOfScalars
    class Scalar
    class ColumnRef
    class DbTable
    class DbColumn
    class DomainRef
    class ContractRef
    class DatasetRef
    class SqlCheckRef
    class NotInSchema
    class Dispatch {
        +complete(role, target, ctx) tuple~CompletionItemInfo~
    }
    class ObjectKeysCompleter {
        +complete(target, ctx) tuple~CompletionItemInfo~
    }
    class ArrayItemsCompleter {
        +complete_object_item(target, ctx) tuple~CompletionItemInfo~
        +complete_scalar_item(target, ctx) tuple~CompletionItemInfo~
    }
    class ScalarValueCompleter {
        +complete(target, ctx) tuple~CompletionItemInfo~
    }
    class RefsCompleter {
        +complete_column(target, ctx) tuple~CompletionItemInfo~
        +complete_contract(ctx) tuple~CompletionItemInfo~
        +complete_dataset(ctx) tuple~CompletionItemInfo~
        +complete_sql_check(ctx) tuple~CompletionItemInfo~
        +complete_domain(ctx) tuple~CompletionItemInfo~
    }
    class DbCompleter {
        +complete_table(ctx) tuple~CompletionItemInfo~
        +complete_column(ctx) tuple~CompletionItemInfo~
    }
    CompletionService --> Dispatch : calls
    CompletionService --> CompletionContext : builds
    Dispatch --> CursorRole : matches on
    Dispatch --> CompletionTarget : matches on
    Dispatch --> ObjectKeysCompleter : routes
    Dispatch --> ArrayItemsCompleter : routes
    Dispatch --> ScalarValueCompleter : routes
    Dispatch --> RefsCompleter : routes
    Dispatch --> DbCompleter : routes
    CompletionTarget <|-- ObjectShape
    CompletionTarget <|-- ArrayOfObjects
    CompletionTarget <|-- ArrayOfScalars
    CompletionTarget <|-- Scalar
    CompletionTarget <|-- ColumnRef
    CompletionTarget <|-- DbTable
    CompletionTarget <|-- DbColumn
    CompletionTarget <|-- DomainRef
    CompletionTarget <|-- ContractRef
    CompletionTarget <|-- DatasetRef
    CompletionTarget <|-- SqlCheckRef
    CompletionTarget <|-- NotInSchema