mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
Five gates broke on the 2026-04-27 push of the smart_crusher branch.
Each is fixed below; the second half adds a `make ci-precheck` target
(plus an installable git pre-push hook) so the same dance never happens
again.
Failures fixed:
1. cargo fmt — 22 files had formatting drift introduced over the
stage 3c.1 work. `cargo fmt --all` reformatted them; no semantic
changes. `cargo test --workspace` still green (388 + supporting).
2. wheels job (macOS x86_64) — `fastembed -> ort -> ort-sys` does not
publish prebuilt ONNX Runtime binaries for `x86_64-apple-darwin`.
Removed that target from `.github/workflows/rust.yml`'s wheels
matrix. Apple Silicon (`aarch64-apple-darwin`) covers macOS
distribution; Intel macOS users can build from source. The matrix
now has 2 targets: linux x86_64 + macOS aarch64.
3. test-extras (relevance.py) — `tests/test_relevance.py::TestSmartCrusherIntegration`
constructs a `SmartCrusher`, which hard-imports `headroom._core`
since the python implementation was retired in stage 3c.1b. The
test-extras job didn't build the rust extension. Added the same
`maturin build + symlink` block the main `test` job uses.
4. smoke-test (eval.yml) — same root cause:
`compression_only.evaluate_ccr_lossless` instantiates a SmartCrusher.
Same fix: build the rust extension before the smoke test runs.
5. commitlint — three rules tripped:
- `subject-case` rejects PascalCase identifiers in subjects, but
the project deliberately names classes (SmartCrusher, HfTokenizer,
ContentRouter, DiffCompressor) in commit subjects. Disabled.
- `footer-leading-blank` is a warning that the wagoid action turns
into a CI failure; lines like `Module: foo.rs` in our bodies
match the conventional footer pattern and trip it. Disabled.
- `type-enum` doesn't include `parity`, but the project ships
parity-test infrastructure as its own concern (separate from
`test:`); added `parity` to the allowed types.
Pre-push verification — the prevention half:
`make ci-precheck` runs all of the above CI gates locally:
- `ci-precheck-rust`: cargo fmt --check + clippy + test --workspace.
- `ci-precheck-python`: builds the rust extension via maturin, then
runs the smart_crusher-affected python test files (185 tests across
test_transforms/, test_relevance*, test_ccr, test_acceptance,
test_critical_fixes, test_quality_retention).
- `ci-precheck-commitlint`: `npx commitlint --from origin/main --to
HEAD` against the same config CI uses. Skipped silently if npx is
not on PATH (install Node 18+ to enable).
`make install-git-hooks` (or `scripts/install-git-hooks.sh`) installs
a git pre-push hook that runs `make ci-precheck` automatically.
Bypass with `--no-verify` only when truly needed.
When new CI gates land in `.github/workflows/`, mirror them into a
`make ci-precheck-*` target. The Makefile is the local mirror of the
CI configuration; keeping them in sync is a load-bearing invariant.
Verification: `make ci-precheck` runs green on this commit.
92 lines
3.4 KiB
YAML
92 lines
3.4 KiB
YAML
name: Evaluation Suite
|
|
|
|
on:
|
|
schedule:
|
|
- cron: '0 6 * * 1' # Weekly on Monday 6am UTC
|
|
workflow_dispatch: # Manual trigger
|
|
pull_request:
|
|
paths:
|
|
- 'headroom/transforms/**'
|
|
- 'headroom/evals/**'
|
|
- 'headroom/compress.py'
|
|
|
|
jobs:
|
|
# Fast smoke test on PRs touching compression code (~$0.05, ~2 min)
|
|
smoke-test:
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.11"
|
|
- name: Install dependencies
|
|
run: pip install -e ".[all]"
|
|
|
|
# `compression_only.evaluate_ccr_lossless` constructs a SmartCrusher
|
|
# which now hard-imports `headroom._core` (Stage 3c.1b). Build the
|
|
# Rust extension before running the smoke test or every call raises
|
|
# `ModuleNotFoundError`. Mirrors the main CI `test` job pattern.
|
|
- name: Install Rust toolchain
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Cache cargo registry + build
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: ". -> target"
|
|
|
|
- name: Install maturin
|
|
run: pip install 'maturin>=1.5,<2.0'
|
|
|
|
- name: Build Rust extension (headroom._core)
|
|
run: |
|
|
set -euo pipefail
|
|
maturin build --release -m crates/headroom-py/Cargo.toml --out dist
|
|
pip install --force-reinstall --no-deps dist/headroom_core_py-*.whl
|
|
SITE_PACKAGES=$(python -c "import site; print(site.getsitepackages()[0])")
|
|
SO_FILE=$(find "$SITE_PACKAGES/headroom" -maxdepth 1 -name "_core.cpython-*.so" -print -quit 2>/dev/null)
|
|
if [[ -z "$SO_FILE" ]]; then
|
|
echo "error: could not find _core.cpython-*.so under $SITE_PACKAGES/headroom/" >&2
|
|
exit 1
|
|
fi
|
|
ln -sf "$SO_FILE" "headroom/$(basename "$SO_FILE")"
|
|
python -c "from headroom._core import SmartCrusher; print('headroom._core OK:', SmartCrusher)"
|
|
|
|
- name: Run CCR round-trip (zero cost)
|
|
run: |
|
|
python -c "
|
|
from headroom.evals.runners.compression_only import CompressionOnlyRunner
|
|
runner = CompressionOnlyRunner()
|
|
cases = runner.generate_ccr_test_cases(n=50)
|
|
result = runner.evaluate_ccr_lossless(cases)
|
|
print(f'CCR Round-trip: {result.passed_cases}/{result.total_cases} passed')
|
|
assert result.passed, f'CCR failures: {result.errors}'
|
|
"
|
|
- name: Run built-in tool output eval
|
|
run: python -m headroom.evals quick -n 8 --provider openai --model gpt-4o-mini
|
|
env:
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
|
|
# Full Tier 1 suite, weekly or manual (~$3-5, ~30-45 min)
|
|
weekly-suite:
|
|
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.11"
|
|
- name: Install dependencies
|
|
run: pip install -e ".[all]"
|
|
- name: Run Tier 1 evaluation suite
|
|
run: python -m headroom.evals suite --tier 1 --ci -o eval_results/
|
|
env:
|
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
- name: Upload results
|
|
if: always()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: eval-results-${{ github.run_number }}
|
|
path: eval_results/
|