# Canonical invocation: python -m <module>
name: CI

on:
  pull_request:
  push:
    branches:
      - main

permissions: read-all

jobs:
  test-and-benchmark:
    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, ubuntu-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Check diff hygiene
        if: matrix.os == 'ubuntu-latest'
        run: git diff --check

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install package
        run: python -m pip install -e ".[server,sbert,rerank]"

      - name: Install test dependencies
        # httpx is required by starlette.testclient (the server tests use TestClient);
        # it used to arrive transitively via chromadb, which is now an optional extra.
        run: python -m pip install pytest httpx

      - name: Linux installer smoke test
        if: matrix.os == 'ubuntu-latest'
        run: sh ./installers/install_seam_linux.sh --dev

      - name: Run tests
        # External (real-service) tests are deselected here so they are NOT
        # silently skipped; they run in the pgvector-integration job. Strict
        # no-skip enforcement (tests/conftest.py) fails the run on any other skip.
        run: python -m pytest test_seam_all/ tools/history/test_history_tools.py tools/streams/ tests/ -m "not external"

      - name: Verify SEAM history integrity
        run: python -m tools.history.verify_integrity

      - name: Verify SEAM history continuity
        run: python -m tools.history.verify_continuity --no-snapshot

      - name: Verify SEAM history routing
        run: python -m tools.history.verify_routing

      - name: Verify SEAM streams
        run: python -m tools.streams.verify_streams

      - name: Run benchmark suite
        run: python -m seam benchmark run all --output benchmark_bundle.json --format json

      - name: Gate benchmark suite
        run: python -m seam benchmark gate benchmark_bundle.json

      - name: External memory benchmark plan
        run: python -m tools.run_external_memory_benchmarks --plan --scope all --format json --output external-memory-benchmark-plan.json

      - name: Upload external memory benchmark plan
        uses: actions/upload-artifact@v4
        with:
          name: external-memory-benchmark-plan
          path: external-memory-benchmark-plan.json

  pgvector-integration:
    runs-on: ubuntu-latest
    services:
      pgvector:
        image: pgvector/pgvector:0.8.2-pg18-trixie
        env:
          POSTGRES_DB: seam_ci
          POSTGRES_USER: seam_ci
          POSTGRES_PASSWORD: seam_ci_password
        ports:
          - 55432:5432
        options: >-
          --health-cmd "pg_isready -U seam_ci -d seam_ci"
          --health-interval 5s
          --health-timeout 5s
          --health-retries 10
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install package
        run: python -m pip install -e ".[server]"

      - name: Install test dependencies
        run: python -m pip install pytest psycopg[binary]

      - name: Run all real-pgvector tests
        # Target the real-service test files explicitly (not `-m external` over all
        # of tests/) so collection does not import server/sbert test modules whose
        # deps this job does not install. PGVECTOR_TEST_DSN gates pk_composite +
        # substream; SEAM_PGVECTOR_DSN gates real_adapter. Strict no-skip
        # (tests/conftest.py, default on) fails the job if any of these skip.
        env:
          PGPASSWORD: seam_ci_password
          SEAM_PGVECTOR_DSN: postgresql://seam_ci@localhost:55432/seam_ci
          PGVECTOR_TEST_DSN: "host=localhost port=55432 dbname=seam_ci user=seam_ci password=seam_ci_password"
        run: python -m pytest tests/audit/test_pgvector_real_adapter.py tests/audit/test_pgvector_pk_composite.py tests/audit/test_substream_isolation.py -q

  package-smoke:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Build wheel and source distribution
        run: |
          python -m pip install build
          python -m build --wheel --sdist

      - name: Install built wheel
        run: python -m pip install dist/*.whl

      - name: Smoke installed commands
        run: |
          seam --help
          seam-mcp --help
          seam-server --help

  repo-hygiene:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Check diff hygiene
        run: git diff --check

      - name: Secret/session URL scan
        shell: bash
        run: |
          if rg --pcre2 -l "(sk-[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|claude\\.ai/(chat|share)/|chatgpt\\.com/(share|c)/)" . \
              --glob '!test_seam/**' \
              --glob '!build/**' \
              --glob '!.venv/**' \
              --glob '!docs/archive/**' \
              --glob '!archive/**' > /tmp/seam_secret_scan_matches; then
            echo "Secret-shaped value or private session URL found in $(wc -l < /tmp/seam_secret_scan_matches) file(s)."
            exit 1
          fi

  chroma-real-smoke:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install package
        run: python -m pip install -e ".[server,chroma]"

      - name: Run real Chroma smoke
        run: python -m tools.ci.chroma_real_smoke

  locomo-quickstart-bil2:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Cache Hugging Face models
        uses: actions/cache@v4
        with:
          path: ~/.cache/huggingface
          key: hf-bge-small-en-v1.5-${{ runner.os }}

      - name: Install package
        run: python -m pip install -e ".[server,sbert]"

      - name: Run LoCoMo quickstart smoke
        run: python -m seam bench external --quickstart locomo --adapter seam --judge stub --output locomo.quickstart.json

      - name: Seal LoCoMo quickstart as BIL-2
        run: python -m seam bench seal locomo.quickstart.json --level BIL-2 --allow-stub-seal --output locomo.quickstart.bil2.json

      - name: Verify LoCoMo quickstart BIL-2 bundle
        run: python -m seam bench verify locomo.quickstart.bil2.json --format json > locomo.quickstart.verify.json

      - name: Upload LoCoMo quickstart artifacts
        uses: actions/upload-artifact@v4
        with:
          name: locomo-quickstart-bil2
          path: |
            locomo.quickstart.json
            locomo.quickstart.bil2.json
            locomo.quickstart.verify.json
