sqlite-graphrag 1.0.36

Local GraphRAG memory for LLMs in a single SQLite file
Documentation
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  fmt:
    name: Formatting
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all --check

  clippy:
    name: Clippy (${{ matrix.os }})
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
      - run: cargo clippy --all-targets --all-features -- -D warnings

  test:
    name: Tests (${{ matrix.os }})
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Cache fastembed ONNX models
        uses: actions/cache@v4
        with:
          path: |
            ~/.cache/fastembed
            ~/Library/Caches/fastembed
            ~\AppData\Local\fastembed\Cache
          key: fastembed-model-multilingual-e5-small-${{ runner.os }}
      - name: Install cargo-nextest
        run: cargo install cargo-nextest --version 0.9.114 --locked
      - name: Run tests with nextest (retry on network flake)
        shell: bash
        env:
          RUST_TEST_THREADS: "2"
          RUSTFLAGS: -D warnings
        run: |
          for attempt in 1 2 3; do
            echo "=== Test attempt $attempt ==="
            if cargo nextest run --profile ci; then
              break
            fi
            if [ "$attempt" -eq 3 ]; then exit 1; fi
            echo "Attempt $attempt failed, retrying in 30s..."
            sleep 30
          done
      - name: Run doctests
        env:
          RUST_TEST_THREADS: "2"
          RUSTFLAGS: -D warnings
        run: cargo test --doc --all-features

  slow-contracts:
    name: Slow Contract Suites
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Cache fastembed ONNX models
        uses: actions/cache@v4
        with:
          path: |
            ~/.cache/fastembed
            ~/Library/Caches/fastembed
            ~\AppData\Local\fastembed\Cache
          key: fastembed-model-multilingual-e5-small-${{ runner.os }}
      - name: Run slow JSON contract suite
        env:
          RUST_TEST_THREADS: "1"
        run: timeout 5400 cargo test --features slow-tests --test doc_contract_integration -- --nocapture
      - name: Run slow PRD compliance suite
        env:
          RUST_TEST_THREADS: "1"
        run: timeout 5400 cargo test --features slow-tests --test prd_compliance -- --nocapture

  doc:
    name: Documentation
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: -D warnings

  msrv:
    name: MSRV (1.88)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@1.88
      - uses: Swatinem/rust-cache@v2
      - run: cargo check --all-features

  audit:
    name: Security Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo install cargo-audit --locked
      - run: cargo audit

  deny:
    name: Dependency Policy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo install cargo-deny --locked
      - run: cargo deny check advisories licenses bans sources

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview
      - uses: Swatinem/rust-cache@v2
      - name: Install cargo-nextest and llvm-cov
        run: |
          cargo install cargo-nextest --version 0.9.114 --locked
          cargo install cargo-llvm-cov --locked
      - name: Coverage with nextest
        env:
          RUST_TEST_THREADS: "2"
        run: cargo llvm-cov nextest --profile heavy --features slow-tests --lcov --output-path lcov.info
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-lcov
          path: lcov.info

  commit-check:
    name: Block Agent Co-Authorship
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Check commit messages for agent co-authors
        run: |
          range="${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
          pattern='(?i)Co-authored-by:.*(Claude|Opus|Sonnet|Haiku|GPT-|Copilot|Cursor|Gemini|Anthropic|OpenAI|dependabot\[bot\]|renovate\[bot\])'
          if git log --format='%B' "$range" | grep -Pq "$pattern"; then
            echo "::error::Commit messages must not include Co-authored-by from AI agents or bots"
            git log --format='%B' "$range" | grep -P "$pattern" || true
            exit 1
          fi
          echo "No forbidden co-authors detected"

  language-check:
    name: Language policy (English-only outside i18n)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install ripgrep
        run: sudo apt-get update && sudo apt-get install -y ripgrep
      - name: Forbid Portuguese in /// doc comments
        run: |
          if rg '///.*[áéíóúâêôãõçÁÉÍÓÚÂÊÔÃÕÇ]' src/ tests/; then
            echo "::error::Portuguese characters found in /// doc comments. Policy: English-only outside i18n.rs."
            exit 1
          fi
      - name: Forbid Portuguese in //! crate-level docs
        run: |
          if rg '//!.*[áéíóúâêôãõçÁÉÍÓÚÂÊÔÃÕÇ]' src/ tests/; then
            echo "::error::Portuguese characters found in //! crate-level docs."
            exit 1
          fi
      - name: Forbid Portuguese in tracing logs
        run: |
          if rg 'tracing::(info|warn|error|debug|trace)!.*[áéíóúâêôãõçÁÉÍÓÚÂÊÔÃÕÇ]' src/; then
            echo "::error::Portuguese in tracing logs. Use English keys/messages."
            exit 1
          fi
      - name: Forbid Portuguese in #[error(...)] attributes
        run: |
          if rg '#\[error.*[áéíóúâêôãõçÁÉÍÓÚÂÊÔÃÕÇ]' src/; then
            echo "::error::Portuguese in thiserror attributes. Use English."
            exit 1
          fi
      - name: Forbid Portuguese-without-accent words in tracing/error/doc/assert/expect/panic
        # v1.0.36 (M1): the accent-only audit gates above missed several PT
        # strings such as `tracing::warn!("NER falhou, usando apenas regex")`,
        # `"batch NER falhou (chunk de N janelas)..."`, and `"falha ao persistir
        # url '...'"`. This gate complements the accent gate by scanning the
        # specific surfaces where PT/EN drift hurts most: log lines, error
        # attributes, doc comments, and runtime assertions.
        # Plain string literals are NOT scanned because intentional fixtures
        # (PT test inputs that exercise multilingual extraction) live there.
        run: |
          PT_PATTERN='\b(falhou|falha|falham|falhar|falhas|janelas?|invalido|invalida|invalidos|invalidas|inicializando|inicializar|inicializa|inicializou|persistir|persistencia|persistido|persistida|configuracao|autenticacao|validacao|verificacao|compactacao|substituicao|usando apenas|nao foi|nao pode|nao tem|nao deve|nao precisa|nao consegue|nao possui|nao encontrou|nao existe|nao sera|ja foi|ja existe|ja tem|ja esta|esperado|requerido|obrigatorio|obrigatoria|obrigatorios|obrigatorias|memoria|memorias|criando|criada|criadas|criados|criou|atualizado|atualizada|atualizados|atualizadas|deletado|deletada|deletados|deletadas|inserido|inserida|inseridos|inseridas|removido|removida|removidos|removidas|busca|propaga|retorna)\b'
          # 1. Tracing macros
          if rg --no-messages -i "tracing::(info|warn|error|debug|trace)!.*${PT_PATTERN}" src/ -g '!i18n.rs'; then
            echo "::error::PT-no-accent word detected in tracing log (src/). Translate or move to i18n.rs."
            exit 1
          fi
          # 2. thiserror attributes
          if rg --no-messages -i "#\[error.*${PT_PATTERN}" src/ -g '!i18n.rs'; then
            echo "::error::PT-no-accent word detected in #[error(...)] (src/). Translate or move to i18n.rs."
            exit 1
          fi
          # 3. /// and //! doc comments
          if rg --no-messages -i "(///|//!).*${PT_PATTERN}" src/ tests/ -g '!i18n.rs'; then
            echo "::error::PT-no-accent word detected in doc comment. Translate to English."
            exit 1
          fi
          # 4. assert/panic/unreachable/bail/ensure/expect macros and methods
          if rg --no-messages -i "(panic|assert|assert_eq|assert_ne|unreachable|todo|unimplemented|bail|ensure|expect)!?\([^)]*${PT_PATTERN}" src/ tests/ -g '!i18n.rs'; then
            echo "::error::PT-no-accent word detected in panic/assert/expect (src/ or tests/). Translate to English."
            exit 1
          fi

  loom:
    name: Loom Concurrency
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Run loom tests
        env:
          RUSTFLAGS: "--cfg sqlite_graphrag_loom"
          LOOM_MAX_PREEMPTIONS: "1"
          LOOM_MAX_BRANCHES: "100"
          RUST_TEST_THREADS: "1"
        run: timeout 600 cargo test --test loom_lock_slots --release -- --test-threads=1

  bench-regression:
    name: Benchmark Regression
    runs-on: ubuntu-latest
    continue-on-error: true
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - name: Download baseline artifact
        uses: actions/download-artifact@v4
        with:
          name: bench-baseline
          path: target/criterion
        continue-on-error: true
      - name: Run benchmarks
        env:
          RUST_TEST_THREADS: "2"
        run: timeout 900 cargo bench --bench regression_baseline -- --quick
      - name: Upload benchmark results
        uses: actions/upload-artifact@v4
        with:
          name: bench-baseline
          path: target/criterion