Using Ingot
Scan a model, read what's wrong with it, fix what's fixable, and gate your pipeline on the verdict. scanning · verdicts · CLI · fixing · CI · API
Scanning a model
Paste any public Hugging Face repo on the models page (or open /models/<owner>/<name> directly) and hit scan — no account needed. The static battery runs in seconds: serialization/pickle risk, remote-code requirements, license drift, and chat-template / tokenizer drift against the claimed parent. Results publish to the model's public page and the shared database, so a model anyone has scanned resolves instantly for everyone after.
Where our deep battery (GPU behavioral differentials, glitch-token probes) has run, those findings merge into the same page — see Qwen/Qwen3.8-27B for what a full result looks like.
What the verdicts mean
Every scan resolves to one verdict, derived from the severity of its findings. The bar for fail is deliberately high — Ingot's claim discipline is that a failing badge means measured damage, not vibes:
- fail — at least one high-severity finding: damaging behavior confirmed on this checkpoint (e.g. glitch tokens measured corrupting user data on every sampled trial). Static metadata checks never produce this on their own; it comes from the deep battery. Most models will never fail — that is the point, not a gap.
- warn — at least one medium-severity finding: a measured risk indicator. Template/tokenizer drift vs. the claimed parent, pickle-only weights, remote-code requirements, license drift, or an undertrained glitch-token surface in the weights (candidates, not yet behaviorally confirmed). This is where most real-world signal lives.
- pass — no medium-or-worse findings in the batteries that have run. Not a safety certification: it means the failure modes we measure came back clean, nothing more.
Practical consequence for CI: gate on --fail-on warn. Gating only on fail means "block confirmed-damaged checkpoints" — a sensible floor, but it will wave through drifted templates and pickle-only weights, which are the failures that actually reach production.
The CLI
@ingotai/scan is a zero-dependency npm CLI (Node ≥ 18). New scans need an API key (sign in → dashboard → create key); reading the public database and patching don't.
# scan a Hugging Face model (needs an API key for new scans) export INGOT_API_KEY=ingot_… npx @ingotai/scan scan owner/model # read the public database — no key needed npx @ingotai/scan report Qwen/Qwen3.8-27B # machine-readable npx @ingotai/scan report Qwen/Qwen3.8-27B --json
Exit codes are CI-friendly: 0 clean (or below the gate), 1 the --fail-on gate hit, 2 usage or network error. You can also scan a local checkpoint directory offline — ingot scan --dir ./path — which checks serialization risk, executable code, and chat-template presence without touching the network.
Fixing what the scan finds
Every finding on a model page carries a How to fix section, and each fix is tagged by what it takes:
- ingot patch — metadata-level: fixable by replacing small config files (a dropped or drifted chat template, for example). The patch manifest is computed from the claimed parent and the published scan, pinned to the exact upstream revision, and content-hashed.
- runtime guard — mitigable at runtime: the deep battery measured specific token strings corrupting on this exact checkpoint, and the guard artifact carries that blocklist.
- weight-level — lives in the weights. No patch or filter removes it; the honest fixes are constraining the task, choosing a checkpoint that scanned clean, or retraining.
ingot patch
Applies the metadata-level fixes to a local copy. Your weights never move — the patch touches small JSON files only, writes INGOT-PATCH.json alongside them for provenance, and prints what was fixed and what wasn't.
# apply the metadata-level fixes to a local copy — no key needed npx @ingotai/scan patch owner/model # → writes ./model-ingot-patched/ with the fixed files + INGOT-PATCH.json # patch an existing local checkout instead npx @ingotai/scan patch owner/model --dir ./my-local-checkpoint # verify (offline — also checks the patch hasn't drifted) npx @ingotai/scan scan --dir ./model-ingot-patched
The runtime guard
For checkpoints with deep-battery glitch data, GET /api/v1/guard/<owner>/<name> returns the scan-derived guard config: the tokens measured corrupting on every sampled trial, plus the low-norm candidate list. The @ingotai/guard npm package is the reference consumer:
import { fetchGuard, screen, assertClean } from "@ingotai/guard";
const guard = await fetchGuard("Qwen/Qwen3.8-27B");
// screen a record before a verbatim-copy task
const { hits, clean } = screen(guard, record.text);
if (!clean) routeToHumanReview(record, hits);
// or hard-gate on confirmed corrupting tokens
assertClean(guard, record.text); // throws with .hitsThe guard's policy is flag-and-reroute, never rewrite: silently transforming the matched string would corrupt the data — exactly the failure the guard exists to prevent. Remediation guidance, patches, and guards address the documented findings only; none of it is a safety certification.
CI integration
Gate your pipeline on the scan verdict. GitHub Actions has a ready-made action; anything else can use the CLI or raw API. Full walkthrough (including plain-curl): CI integration →
- name: Ingot model scan
uses: Ember-Sovereignty/ingot/ci@main
with:
model: owner/model
api-key: ${{ secrets.INGOT_API_KEY }}
fail-on: warn # recommended — gate on measured risk, not only confirmed damage# any CI system — exit 1 when the gate hits npx @ingotai/scan scan owner/model --fail-on warn
API reference
| Endpoint | Auth | What it does |
|---|---|---|
| POST /api/v1/scans | key | Queue a scan. Body: {"model": "owner/name"}. |
| GET /api/v1/scans/:id | key | Poll status: queued → running → complete, with the verdict. |
| GET /api/v1/models/:owner/:name | none | Published analysis: verdict, findings with per-finding remediation, patch/guard pointers. |
| GET /api/v1/models/:owner/:name/badge.svg | none | Verdict badge for READMEs. |
| GET /api/v1/patch/:owner/:name | none | Patch manifest: metadata-level fix operations + the honest unaddressed list. Applied locally by ingot patch. |
| GET /api/v1/guard/:owner/:name | none | Scan-derived runtime guard config (content-hashed). 404 means "no deep-battery data yet", never "clean". |