# GIF Forge — a Bounded Agent Harness builder pack

**What it does:** forces a code model (DeepSeek by default) to produce a
real animated GIF — not a description of one, not an HTML page instead of
one — by making it write a Python/Pillow render script under a frozen,
machine-checked acceptance.

**Why it exists:** asked raw for "the most impressive .gif of a spacex
starship catch that you can," DeepSeek returned an HTML canvas page, a
thermos-shaped booster, and a black void. Under this loop the same model
produced a 960×540, 72-frame looping GIF with a real background, correct
proportions, a flame, working catch arms, smoke and engine glow. The
model didn't get smarter. The structure did the work. Full case study:
https://boundedagentharness.com/forge/gif-forge/

## The loop

1. **Contract** (`contract-template.md`) — you describe the scene as
   layout constants and measurable claims, not vibes.
2. **Frozen acceptance** (`acceptance-template.md`) — before any
   generation, write the gates a checker can measure. Freeze them.
3. **Sealed author** (`cycle.py`) — the model writes the whole render
   script. It never sees the checker.
4. **Deterministic checker** (`checker-template.py`) — measures the GIF:
   format, background, motion, and YOUR scene claims. Emits a contact
   sheet for the one thing machines can't grade: whether it reads.
5. **Bounded repairs** — failures go back verbatim (exact traceback,
   exact failing numbers). At most 4 generation rounds. Miss the bar and
   you report the loss with the measurements — you never lower the bar.

## Quickstart

```bash
pip install pillow
export FORGE_API_KEY=sk-...            # your key — DeepSeek by default
# optional: export FORGE_API_BASE=https://api.deepseek.com
# optional: export FORGE_MODEL=deepseek-chat
cp contract-template.md my-contract.md # fill in YOUR scene
cp acceptance-template.md my-acceptance.md
python3 cycle.py my-contract.md r1     # generates render.py and runs it
python3 checker-template.py out.gif r1 # measures it (add your checks!)
```

Any OpenAI-compatible chat endpoint works — set `FORGE_API_BASE` /
`FORGE_MODEL` for Qwen, OpenRouter, a local server, whatever you have.

## The honest limitation

The loop generalizes. The measurements don't. The Starship checker knew
where the booster was because the contract pinned it there. For your
scene, YOU pick three to six claims a script can measure (a position, a
count, a color family, a before/after difference). That choice — turning
"impressive" into numbers before the model starts — is the entire method.

## Checker corrections are disclosed, never silent

In the Starship run, the frozen flame gate demanded neon-saturated orange
and scored a visibly present rust-toned flame as zero. The correction —
what the predicate got wrong, the re-measured number — was written into
the run report, not quietly patched. If your checker lies to you, fix it
in the open the same way.

## Adding to the Forge

The Forge is a shelf, not a monument. New snippets and builders land
alongside this one as their authors contribute them. A Forge entry needs:
a name, a one-line claim, an author line, a worked example with real
measurements, the files, and its limitations stated on its page. If it
can't state what would prove it failed, it doesn't go on the shelf.
