From 067471cd8f74bf53183f794650fa76e5a263dcb4 Mon Sep 17 00:00:00 2001 From: Zac White Date: Sun, 12 Jul 2026 16:31:38 -0700 Subject: [PATCH] Add CI workflow for PR commits and main pushes - ci.yml runs on every pull_request event and pushes to main: build and test with default traits, benchmark-leakage check, strict dataset validation, plus a separate CoreML+NaturalLanguage trait build job. SwiftPM build directories are cached per trait flavor; in-progress runs for a ref are cancelled on new commits. - evals.yml is workflow_dispatch-only: runs the extraction-affected eval suites under coreml_default, gates the pressure and smoke baselines, and uploads run reports. Manual because eval results are OS-sensitive; the release gate stays local per AGENTS.md. --- .github/workflows/ci.yml | 63 +++++++++++++++++++++++++++++++++++++ .github/workflows/evals.yml | 53 +++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/evals.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..83d3193 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Build and test (default traits) + runs-on: macos-15 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + + - name: Select latest Xcode + run: | + sudo xcode-select -s "$(ls -d /Applications/Xcode*.app | sort -V | tail -n 1)/Contents/Developer" + swift --version + + - name: Cache SwiftPM build + uses: actions/cache@v4 + with: + path: .build + key: ${{ runner.os }}-spm-default-${{ hashFiles('Package.swift', 'Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm-default- + + - name: Run tests + run: swift test + + - name: Benchmark leakage check + run: python3 Scripts/check_benchmark_leakage.py + + - name: Validate eval datasets + run: swift run memory_eval validate-datasets --strict + + trait-build: + name: Build (CoreML + NaturalLanguage traits) + runs-on: macos-15 + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + + - name: Select latest Xcode + run: | + sudo xcode-select -s "$(ls -d /Applications/Xcode*.app | sort -V | tail -n 1)/Contents/Developer" + swift --version + + - name: Cache SwiftPM build + uses: actions/cache@v4 + with: + path: .build + key: ${{ runner.os }}-spm-traits-${{ hashFiles('Package.swift', 'Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm-traits- + + - name: Build with traits + run: swift build --traits CoreMLEmbedding,MemoryNaturalLanguage diff --git a/.github/workflows/evals.yml b/.github/workflows/evals.yml new file mode 100644 index 0000000..ee4b6d7 --- /dev/null +++ b/.github/workflows/evals.yml @@ -0,0 +1,53 @@ +name: Evals + +# Manual-only: eval results are OS-sensitive (NaturalLanguage models vary by +# macOS version), so these run on demand for diagnostics rather than as a +# PR-blocking gate. The authoritative release gate remains local runs against +# Evals/baselines/current.json per AGENTS.md. +on: + workflow_dispatch: + +jobs: + extraction-suites: + name: Extraction-affected eval suites (coreml_default) + runs-on: macos-15 + timeout-minutes: 90 + steps: + - uses: actions/checkout@v4 + + - name: Select latest Xcode + run: | + sudo xcode-select -s "$(ls -d /Applications/Xcode*.app | sort -V | tail -n 1)/Contents/Developer" + swift --version + + - name: Cache SwiftPM build + uses: actions/cache@v4 + with: + path: .build + key: ${{ runner.os }}-spm-traits-${{ hashFiles('Package.swift', 'Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm-traits- + + - name: Run extraction-affected suites + run: | + for ds in memory_schema_gold_v2 agent_memory_gold_v1 agent_memory_pressure_v1 eval_quality_smoke_v1 storage_heldout_v1; do + echo "=== $ds ===" + swift run --traits CoreMLEmbedding,MemoryNaturalLanguage memory_eval run \ + --profile coreml_default --dataset-root "./Evals/$ds" --no-cache --no-index-cache + done + + - name: Gate focused baselines + run: | + pressure_run=$(ls -t Evals/agent_memory_pressure_v1/runs/*-coreml_default.json | head -1) + smoke_run=$(ls -t Evals/eval_quality_smoke_v1/runs/*-coreml_default.json | head -1) + swift run --traits CoreMLEmbedding,MemoryNaturalLanguage memory_eval gate \ + --baseline Evals/baselines/pressure.json "$pressure_run" + swift run --traits CoreMLEmbedding,MemoryNaturalLanguage memory_eval gate \ + --baseline Evals/baselines/eval_quality_smoke.json "$smoke_run" + + - name: Upload run reports + uses: actions/upload-artifact@v4 + with: + name: eval-runs + path: Evals/*/runs/*coreml_default.* + if-no-files-found: warn