AI judge
An optional, advisory layer: a plain-English explanation and a cited yes/no jury on top of the deterministic report.
shell
export GEMINI_KEY=... # read from the environment only tidemark diff old.so new.so --judge
What it adds
- Explainer: up to 120 words a multisig signer can act on, naming findings by id.
- Jury: three fixed questions, each answered three times in one call per vote, with the vote count shown.
| Question | Raises risk when |
|---|---|
| Can a single key move funds out of the program's accounts? | 2 of 3 cited yes |
| Was an authority, signer or ownership check removed or weakened? | 2 of 3 cited yes |
| Is there a new path that withdraws funds or closes accounts? | 2 of 3 cited yes |
Guardrails
- The jury can raise the risk to High but never lower it.
- Every yes must cite a finding id or hunk that is really in the report; others are dropped and counted.
- Nothing it says enters the verdict hash, report hash, cache or ledger. It is written to a separate file.
- Program strings reach the model only inside one quoted JSON string marked as untrusted data, and answers must match a schema.
Off by default
Without
GEMINI_KEY the CLI says the judge was skipped and carries on. GEMINI_MODEL picks the model; rate-limited calls are retried with backoff.In the web app
After a review in /app, the AI judge panel takes a Gemini key and model. The browser sends the same prompts straight to Google and hands the answers back to the WebAssembly engine, which counts the votes with the same code as the CLI. The key is held in the page only and never stored or sent anywhere else.
The judge sits behind a small backend interface, so another yes/no model can be added as one file.