Skip to content

Run kept checks in CI

Once a problem is a kept check, geo ci re-runs it on every change and fails the build if the mistake returns. This guide shows the Docker image, the installer and the exit codes.

In your project folder, geo ci it runs the project’s automatic checks, then re-runs the kept checks stored under .geometer/regressions/. It writes a summary in plain text, and optionally a JSON report and a JUnit XML file. After the run it adds what Guard does with each action: its level now (0 or 1) and, for an action nothing watches yet, what would turn Guard on and whether it is met, missing or not known yet. That does not change the exit code.

Exit codes of geo ci

Code Meaning What to do
0 Nothing failed. Continue.
1 A confirmed problem, or a kept check that reproduced a problem. Fail the build. A mistake you fixed has returned, or a new one was found.
2 Required evidence is missing, or nothing could be checked. Also a kept check that was inconclusive or incompatible. Decide whether to fail. Most teams treat this as a failure, because it means nothing was shown.
3 An infrastructure failure, for example Docker is not running, or a kept check could not run. Fix the runner and run again.

Suggested rules that broke are reported as candidates and never fail the run. A rule fails CI only when you declared it or chose Also check it in CI. Add --require-exercised to treat approved rules that no run exercised as missing evidence (exit 2).

Options of geo ci

Option What it does
[PATH] The project folder. The default is the current folder.
--json Print the JSON report on standard output.
--report FILE Also write the JSON report to a file. It lists each kept check’s result under kept_checks and the autonomy progress under autonomy_progress.
--junit FILE Write JUnit XML. Kept checks appear as one test case each in a geometer.kept suite.
--budget SECONDS Wall-clock limit for agent exploration.
--declarations DIR Use a declarations folder instead of the project’s .geometer/, for a project you must not modify.
--require-exercised Count approved rules that no run exercised as missing evidence.
--snippet github Print the GitHub Actions workflow below and exit; it runs nothing.
--assessment DIR Also create the check’s assessment report and write it into DIR, and print its id. If it cannot be written, a run that would exit 0 exits 3.

After you keep a check, Geometer says:

To run kept checks in CI, add: .github/workflows/geometer.yml (copy from `geo ci --snippet github`)

The command and the example below print one file.

geo ci --snippet github > .github/workflows/geometer.yml

The image ghcr.io/geometerlabs/geo:0.1.0-alpha.2 is for Linux CI. It runs geo and uses the host’s Docker through the mounted socket. It starts no Docker of its own.

docker run --rm --network host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD:$PWD" -w "$PWD" \
ghcr.io/geometerlabs/geo:0.1.0-alpha.2 ci
  • Mount the project at the same path, as above (-v "$PWD:$PWD" -w "$PWD"), because Geometer starts containers that need to see it.
  • Host networking is recommended, not required. It lets Geometer reach a model on the host, such as a local Ollama.
  • The image runs as root, so a file it writes into your project, for example a kept check, belongs to root on the host.
  • Each run starts with empty records.
  • The image is about 250 MB. It carries the Docker command line with the compose and buildx plugins, because without compose Geometer finds no services.

A GitHub Actions workflow that uses the image (the same text as geo ci --snippet github):

name: geometer
on: [pull_request]
jobs:
kept-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Geometer's kept checks
run: |
docker run --rm --network host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD:$PWD" -w "$PWD" \
ghcr.io/geometerlabs/geo:0.1.0-alpha.2 ci \
--report geometer-report.json --junit geometer-junit.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: geometer
path: |
geometer-report.json
geometer-junit.xml

On any runner where you may install a program for your user, use the one-line installer and call geo directly:

name: geometer
on: [pull_request]
jobs:
kept-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Geometer
run: |
curl -fsSL https://geometer.dev/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Run Geometer's kept checks
run: geo ci --report geometer-report.json --junit geometer-junit.xml

The installer checks the download against the release’s SHA256SUMS before it installs. To pin a version, set GEO_VERSION for the shell that runs the script, for example curl -fsSL https://geometer.dev/install.sh | GEO_VERSION=0.1.0-alpha.2 sh. See Install.

A step fails when geo ci exits with anything other than 0, which is the right default. If you want a different rule for exit code 2, run the command and look at the code:

set +e
geo ci --junit geometer-junit.xml
code=$?
set -e
case "$code" in
0) echo "No failures." ;;
1) echo "A problem was found or came back."; exit 1 ;;
2) echo "Evidence was missing: nothing was shown for something required."; exit 1 ;;
*) echo "Geometer could not run (code $code). Check Docker on this runner."; exit 1 ;;
esac