feat(site): the explainer's opening, a CSP on every page, and the calculator fixes (phase 7) #50
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| # A branch pushed to origin and then opened as a pull request fired both | |
| # triggers, so every pull request ran all four jobs twice. The push trigger is | |
| # restricted to main, which is the only branch where a push is not already | |
| # covered by a pull request. pull_request stays unfiltered so a request from | |
| # any branch or fork is checked. | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| # Nothing here pins its dependencies beyond uv.lock's resolution, so a | |
| # transitive release can break the build with no commit of ours involved. | |
| # Weekly is often enough to find that while it is still a small problem, and | |
| # rare enough that nobody learns to ignore the mail. | |
| schedule: | |
| - cron: "17 6 * * 1" | |
| workflow_dispatch: | |
| # No secrets are used anywhere in this workflow, and none should be added. | |
| # Every test must pass with no network connection and no API key. A test that | |
| # needs either is wrong and gets marked and excluded, not accommodated with a | |
| # secret. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| check: | |
| name: ${{ matrix.os }} / Python ${{ matrix.python }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest] | |
| python: ["3.12", "3.13"] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| enable-cache: true | |
| - name: Sync dependencies | |
| # The local extra (torch, transformers) is deliberately not installed. | |
| # plumbline must import and run hosted-only, and CI is where that stays | |
| # true. | |
| run: uv sync --locked | |
| - name: Lint | |
| run: uv run ruff check . | |
| - name: Format | |
| run: uv run ruff format --check . | |
| - name: Types | |
| run: uv run mypy --strict | |
| - name: Tests | |
| run: uv run pytest | |
| # The unit suite has twice now passed while the path a new user takes first | |
| # was broken: an adapter that raised a bare TypeError when a setting was | |
| # missing, and a local arm that failed every case with the reason visible | |
| # only inside the artifact. Both were found by hand. This job walks the | |
| # README quickstart instead of trusting it. | |
| quickstart: | |
| name: quickstart, as the README documents it | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.13" | |
| enable-cache: true | |
| - name: Sync dependencies | |
| run: uv sync --locked | |
| - name: Run the quickstart command verbatim | |
| run: | | |
| uv run plumbline run datasets/public/jevbench-hard.jsonl \ | |
| --adapter mock --format jevbench \ | |
| --results results --report results/report.md | |
| - name: The report says what it is supposed to say | |
| run: | | |
| test -f results/report.md || { echo "no report written"; exit 1; } | |
| grep -q "ECE" results/report.md | |
| # The inconclusive verdict must not regress to reading as a pass. | |
| grep -q "INCONCLUSIVE" results/report.md | |
| grep -q '"INCONCLUSIVE" is not a pass' results/report.md | |
| # Every calibration figure carries its row count and its floor. | |
| grep -q "calibrated-model floor" results/report.md | |
| - name: Following the quickstart leaves the clone clean | |
| run: | | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "the quickstart dirtied the working tree:" | |
| git status --porcelain | |
| exit 1 | |
| fi | |
| - name: The other documented commands work | |
| run: | | |
| uv run plumbline --help > /dev/null | |
| uv run plumbline adapters | grep -q mock | |
| test "$(uv run plumbline version)" = "$(uv run python -c 'import plumbline; print(plumbline.__version__)')" | |
| - name: A missing required setting refuses instead of crashing | |
| run: | | |
| set +e | |
| out="$(uv run plumbline run datasets/public/jevbench-hard.jsonl \ | |
| --adapter local_logits --format jevbench --limit 1 \ | |
| --results results 2>&1)" | |
| set -e | |
| echo "$out" | grep -q "requires" || { echo "expected a named refusal, got:"; echo "$out"; exit 1; } | |
| echo "$out" | grep -qv "Traceback" || { echo "traceback leaked"; exit 1; } | |
| # The house style has no em dashes, and the report's own strings are prose a | |
| # reader sees. datasets/public/ is excluded because it holds vendored | |
| # third-party rows that are reproduced as published. | |
| prose: | |
| name: no em dashes in the docs or the report strings | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Tracked markdown and src/ contain no em dash | |
| run: | | |
| if git grep -n -P '\x{2014}' -- '*.md' 'src/' ':!datasets/public/'; then | |
| echo "::error::em dash found above; use a comma, colon, parentheses, or a new sentence" | |
| exit 1 | |
| fi | |
| # Gate 6 found that the built distribution is a different artifact from the | |
| # source tree: the entry point, the optional extra boundary, and py.typed all | |
| # only exist once packaged. | |
| wheel: | |
| name: the built wheel installs and runs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.13" | |
| enable-cache: true | |
| - name: Build | |
| run: uv build | |
| - name: Install the wheel alone, into a clean environment | |
| run: | | |
| uv venv --python 3.13 /tmp/venv | |
| uv pip install --python /tmp/venv/bin/python dist/*.whl | |
| - name: The entry point resolves and the package is importable | |
| run: | | |
| /tmp/venv/bin/plumbline version | |
| /tmp/venv/bin/plumbline adapters | grep -q typesafe_wire | |
| /tmp/venv/bin/python -c "import plumbline" | |
| - name: The local extra is genuinely optional | |
| run: | | |
| /tmp/venv/bin/python - <<'PY' | |
| import importlib.util as u | |
| for name in ("torch", "transformers"): | |
| assert u.find_spec(name) is None, f"{name} leaked into the core install" | |
| print("core install carries neither torch nor transformers") | |
| PY | |
| - name: py.typed ships, so downstream annotations are visible | |
| run: | | |
| /tmp/venv/bin/python - <<'PY' | |
| import pathlib, plumbline | |
| marker = pathlib.Path(plumbline.__file__).parent / "py.typed" | |
| assert marker.is_file(), "py.typed missing from the installed package" | |
| print("py.typed present at", marker) | |
| PY |