# Kindgi 0.3.1

> What's fixed in Kindgi 0.3.1, and the steps to upgrade to it from 0.3.0.

Released November 1, 2026. For the docs of this version, see [docs.kindgi.com/v0.3.1](https://docs.kindgi.com/v0.3.1/).

## Fixed

- **A guardrail of kind `llm-judge` defined in a pack is judged.** The pack's index now carries the guardrail's `judgeCapabilities`, and the runtime picks its judge model by them, both deployed and in `kindgi dev`. `kindgi build` and `kindgi dev` now refuse an `llm-judge` guardrail that sets no `judgeCapabilities`, and name it.

- **In `kindgi dev`, a pack guardrail keeps its `at`, `sees` and `budget`.** It runs where it runs when deployed, sees what it sees there, and, before or after a tool call or at a model step, has its time limit (`budget.maxLatencyMs`).

- **On a deployed runtime, a guardrail whose check is the pack's own code runs before or after a tool call, or at a model step, when its check lists that point in `points`.** A deploy now keeps the points each of the pack's checks lists.

- **Redeploying a pack in which a guardrail changed only its `at` or `sees` is refused as a changed definition**, like a change to `action` or `config`. Before, the deploy succeeded and the guardrail went on with its old `at` and `sees`.

- **`GET /v1/guardrails` and `GET /v1/guardrails/{guardrailId}` return a guardrail's `at` and `sees`**, as the API schema has described them since 0.3.0. A guardrail that sets neither still returns neither: it runs at the final answer and sees the turn.

- **On Cloud Run, `upgrade.sh` upgrades a 0.2.0 deployment whose database has a private IP.** 0.3.0's change to the database instance, Cloud SQL's own deletion protection, makes the module read the instance's CA certificates during the apply. So the same plan shows the server's `KINDGI_DATABASE_SERVER_CA` as `(known after apply)`. The plan check now accepts that change only with a private-IP database, and only beside the instance's change. Any other change still stops it.

- **On Cloud Run, `upgrade.sh`'s backup waits while its new grant on the backup bucket takes effect.** The script grants the Cloud SQL instance's service account `roles/storage.objectAdmin` on the bucket, then exports the database there. While a new grant takes effect, the export can fail with HTTP 403 and "failed to initiate resumable upload". The script waited out Cloud SQL's 412 for the same cause, but not this 403, so a first upgrade could stop at its backup with "the export failed (above). Nothing has changed. Fix the cause and run again." It now waits out the 403 the same way, for up to 7 minutes in all. Any other error still stops it at once.

## Known issues

- **Erasing a person's data leaves their words in test runs that had already finished.** For each case from that person's runs, the erasure clears what a run on the test cases could quote: the case's `changes`, `tools`, `stopped` and `error`, and what differed from what the run should have done. But a run that had already finished keeps its own copy of those results, its `perCase`, and the erasure leaves that copy as it was, so the run still shows them. This has been so in every release since erasure first covered test runs. Fixed in 0.4.0.

## Upgrade steps

Upgrade the runtime, the `kindgi` CLI and the pack's SDK to 0.3.1, then rebuild and redeploy each pack that has guardrails.

- **Redeploy each pack with a guardrail at `before-tool`, `after-tool` or `model-step`.** A pack deployed before 0.3.1 has no points stored for its checks, so until its next deploy such a guardrail still can't run its check there (`check-point-unsupported`), as in 0.3.0.

- **Every `llm-judge` guardrail a deploy before 0.3.1 registered:** it was stored without `judgeCapabilities`, even when the pack set them, so it still never judges. Make sure the pack sets them (`kindgi build` now refuses one that doesn't). The next deploy is then refused with HTTP 409 `guardrail-already-registered` and this message:

  > The guardrail `<id>` wasn't published: it is already registered with a different definition; unregister it (`kindgi guardrails unregister <id>`) and deploy again; nothing was deployed

  Run `kindgi guardrails unregister <id>`, then deploy again. Until that deploy, the guardrail doesn't run, so deploy right after unregistering.

- **A guardrail whose `at` or `sees` changed while an earlier deploy kept it with the old ones:** its pack's next deploy is refused the same way, with the same message. Unregister it, then deploy again. Until that deploy, the guardrail doesn't run, so deploy right after unregistering.

- **Rolling back to 0.3.0:** a 0.3.0 runtime ignores the stored points, so a pack guardrail before or after a tool call or at a model step is back to 0.3.0's known issue: its check can't run there. A pack deployed while on 0.3.0 loses its stored points, so after returning to 0.3.1, redeploy it once.

- **From 0.2.0 on Cloud Run with a private-IP database:** run 0.3.1's `upgrade.sh`. It takes the deployment to 0.3.1 in one run, making 0.3.0's change to the instance on the way. Before you confirm, the plan shows the instance's deletion protection turning on, and the server's `KINDGI_DATABASE_SERVER_CA` as `(known after apply)`. That's expected: it's still the instance's CAs. If the plan says the instance must be replaced, answer no. A replace deletes the database, and the plan check stops on one before it asks.
