name: ci

on:
  pull_request:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  PYTHON_VERSION: "3.11"
  CI: "1"

jobs:
  lint:
    name: Focused lint
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Install
        run: |
          python -m pip install --upgrade pip
          python -m pip install -e ".[dev]"
      - name: Ruff focused surface
        run: |
          python -m ruff check \
            lib/agent_routing.py \
            lib/config.py \
            lib/db.py \
            lib/evaluate.py \
            lib/llm.py \
            lib/post_extract.py \
            ops/apply_gcp_iam_split.py \
            ops/capture_vps_canonical_postgres_snapshot.py \
            ops/check_gcp_infra_readiness.py \
            ops/run_gcp_infra_execute_canary.py \
            ops/apply_gcp_runtime_baseline.py \
            ops/check_gcp_service_communications.py \
            ops/plan_gcp_iam_split.py \
            ops/redact_sqlite_postgres_restore_canary.py \
            ops/restore_gcp_generated_postgres_snapshot.py \
            ops/sqlite_to_postgres_dump.py \
            ops/verify_gcp_cloudsql_restore_readback.py \
            ops/verify_postgres_parity_manifest.py \
            telegram/approvals.py \
            hermes-agent/leoclean-bin/kb_tool.py \
            hermes-agent/leoclean-bin/cloudsql_memory_tool.py \
            scripts/check_crabbox_ci_contract.py \
            scripts/check_llm_refinement_contract.py \
            scripts/build_working_leo_m3taversal_outcome_sandbox.py \
            scripts/leo_behavior_manifest.py \
            scripts/leo_tool_trace.py \
            scripts/replay_decision_engine_eval.py \
            scripts/prove_phase1b_local.py \
            scripts/run_gcp_generated_db_direct_claim_suite.py \
            scripts/run_gcp_generated_db_blind_claim_canary.py \
            scripts/run_leo_direct_claim_handler_suite.py \
            scripts/run_leo_m3taversal_oos_handler_suite.py \
            scripts/verify_leo_db_first_oos_canary.py \
            scripts/run_leo_clone_bound_handler_checkpoint.py \
            scripts/working_leo_m3taversal_oos_benchmark.py \
            scripts/working_leo_open_ended_benchmark.py \
            tests/test_agent_routing.py \
            tests/test_assemble_telegram_visible_direct_claim_capture_receipt.py \
            tests/test_build_working_leo_m3taversal_outcome_sandbox.py \
            tests/test_decision_engine_replay.py \
            tests/test_evaluate_agent_routing.py \
            tests/test_gcp_artifact_workflow.py \
            tests/test_capture_vps_canonical_postgres_snapshot.py \
            tests/test_gcp_infra_execute_canary.py \
            tests/test_gcp_infra_readiness_checker.py \
            tests/test_gcp_runtime_baseline_apply.py \
            tests/test_gcp_service_communications.py \
            tests/test_gcp_cloudsql_restore_drill.py \
            tests/test_gcp_cloudsql_restore_readback.py \
            tests/test_gcp_iam_split_apply.py \
            tests/test_gcp_iam_split_plan.py \
            tests/test_gcp_readiness_workflow.py \
            tests/test_gcp_generated_db_direct_claim_suite.py \
            tests/test_gcp_generated_db_blind_claim_canary.py \
            tests/test_hermes_leoclean_kb_bridge_source.py \
            tests/test_hermes_leoclean_skill_surfaces.py \
            tests/test_leo_behavior_manifest.py \
            tests/test_leo_tool_trace.py \
            tests/test_verify_leo_db_first_oos_canary.py \
            tests/test_compile_kb_source_packet.py \
            tests/test_verify_postgres_parity_manifest.py \
            tests/test_working_leo_m3taversal_oos_benchmark.py \
            tests/test_working_leo_open_ended_benchmark.py \
            tests/test_phase1b_end_to_end.py \
            tests/test_restore_gcp_generated_postgres_snapshot.py \
            tests/test_sqlite_to_postgres_dump.py \
            tests/test_sqlite_postgres_restore_canary_capsule.py \
            tests/test_eval_parse.py \
            tests/test_contributor.py \
            tests/test_search.py
      - name: Shell syntax
        run: |
          bash -n \
            ops/backup_vps_sqlite_kb.sh \
            ops/run_gcp_cloudsql_restore_drill.sh \
            ops/run_sqlite_postgres_restore_canary.sh

  test:
    name: Unit tests
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Install
        run: |
          python -m pip install --upgrade pip
          python -m pip install -e ".[dev]"
      - name: Pytest
        run: |
          mkdir -p .crabbox-results
          python -m pytest --junitxml=.crabbox-results/pytest.xml
      - name: Upload test artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: teleo-infrastructure-pytest
          path: .crabbox-results/pytest.xml
          if-no-files-found: warn

  repo-contracts:
    name: Repo contracts
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Install
        run: |
          python -m pip install --upgrade pip
          python -m pip install -e ".[dev]"
      - name: Validate repo-owned contract
        run: |
          python scripts/check_crabbox_ci_contract.py \
            --output .crabbox-results/crabbox-ci-contract.json
          python scripts/check_llm_refinement_contract.py \
            --output .crabbox-results/llm-refinement-contract.json
          python scripts/replay_decision_engine_eval.py \
            --output .crabbox-results/decision-engine-eval.json
      - name: Upload contract artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: teleo-infrastructure-repo-contracts
          path: |
            .crabbox-results/crabbox-ci-contract.json
            .crabbox-results/llm-refinement-contract.json
            .crabbox-results/decision-engine-eval.json
          if-no-files-found: error

  phase1b-local-proof:
    name: Phase 1B local proof
    runs-on: ubuntu-latest
    needs:
      - lint
      - test
      - repo-contracts
    timeout-minutes: 20
    env:
      PHASE1B_AGENT_ROUTING_ENABLED: "true"
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
      - name: Install
        run: |
          python -m pip install --upgrade pip
          python -m pip install -e ".[dev]"
      - name: Run proof wrapper
        run: |
          scripts/crabbox_phase1b_proof.sh
      - name: Upload proof artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: teleo-infrastructure-phase1b-proof
          path: |
            .crabbox-results/crabbox-ci-contract.json
            proof/phase1b-local-e2e-proof.json
            .crabbox-results/phase1b-pytest.xml
            .crabbox-results/phase1b-proof-summary.json
          if-no-files-found: warn
