# Forge Field Manual No.11 & No.12 — publication package

Measured 27 August 2026 on one machine. Every figure traces to a run on that box.

---

## publish/

What goes on ferroxlabs.com.

| file | notes |
|---|---|
| `no11-fragment.html` | **No.11** ready to drop in. CSS scoped under `.fm-article`; inherits your `--canvas` / `--forge` tokens rather than redefining them. No `<nav>`, no `body{}` — the host page owns those. |
| `no12-fragment.html` | **No.12**, same treatment. 398 KB, mostly the five embedded orrery stills. |
| `no11-standalone.html` | Tokens + nav included, for previewing outside the site. |
| `no12-standalone.html` | As above. |

**Video is a YouTube embed** (`youtube-nocookie.com/embed/Rt9Wqd0LKnw`), not a local file. It renders
normally on your site. It does **not** render in a Claude artifact preview — that viewer's CSP blocks
external iframes. A preview limitation, not a page bug.

### Integration
- Assumes these tokens exist on the page: `--canvas`, `--canvas-2`, `--surface`, `--elevated`,
  `--border`, `--border-strong`, `--text-bright`, `--text`, `--text-muted`, `--text-dim`,
  `--forge`, `--forge-soft`, `--forge-deep`. They do on ferroxlabs.com.
- Assumes Inter (`opsz 14..32, wght 300..700`) and JetBrains Mono (400/500) are loaded. Both are.
- Neither fragment contains page-level JS. Safe to inline.
- Verified: 133 and 93 scoped rules respectively, zero unscoped `body` / `:root` / `html` selectors.

---

## Data provenance

Every published figure in both manuals was verified against its raw file. Audit result:

```
[hard task suite]           5/5 MATCH
[interactive agent loop]    5/5 MATCH
[orrery, final render]      5/5 MATCH

ALL PUBLISHED FIGURES MATCH THEIR RAW FILES
```

An earlier gap — the Opus rows in `results/agentloop.json` overwritten by a local-only run — has been
closed by re-running `node agentbench.mjs api`. Two figures moved slightly on re-measurement and the
manuals were corrected to match: **Opus 4.6 89% → 88%**, **Opus 5 95% → 99%**.

---

## raw-3d/

Unedited model output for both 3D tasks.

- `orrery/` — the bright orrery: five model pages plus `live.html`, the side-by-side harness
  (2 local on top, 3 Claude underneath, `SYNC START` to restart together). This is what the YouTube
  recording captures.
- `solar-system/` — the earlier realistic version, kept because it produced the first instance of the
  Qwen-extras finding.

Serve over HTTP — **not** `file://`, the iframes need an origin:

```
cd raw-3d/orrery
node -e "const h=require('http'),f=require('fs'),p=require('path');h.createServer((q,s)=>{const u=q.url==='/'?'/live.html':q.url.split('?')[0];const t=p.join(process.cwd(),u);if(!f.existsSync(t)){s.writeHead(404);return s.end()}s.writeHead(200,{'Content-Type':u.endsWith('.html')?'text/html':'application/octet-stream'});f.createReadStream(t).pipe(s)}).listen(8777,()=>console.log('http://127.0.0.1:8777'))"
```

---

## evidence/

The failures, kept deliberately.

| file | what it shows |
|---|---|
| `ornith-attempt1-FAILED.html` | Passes all 16 structural checks, renders a **blank frame**. One line: `.emissive` assigned onto a `MeshBasicMaterial`, which has no such property → `TypeError` inside Three.js every frame. Delete that line and it renders fully (2,286 B → 24,830 B). |
| `ornith-attempt2-broken-render.html` | The first replacement. Passed the *old* render gate (30 KB PNG, frames differed) while being flat black regions and a stray polygon. This is why the gate was rewritten. |
| `*_t2.png` | Verification frames for all five. |
| `ornith-retry.json` | Every re-sampling attempt with its measurements. |

---

## benchmark/

Rerunnable harness.

```
node run2.mjs api        # 6 hard tasks vs Opus 4.6 / 4.8 / 5   (needs ANTHROPIC_API_KEY)
node run2.mjs local      # same tasks vs the local GGUF models
node agentbench.mjs all  # interactive agent loop, 3 reps each
node orrery.mjs          # the bright orrery across all five
node orrery-regrade.mjs  # re-score orrery output from disk, no model calls
node rendercheck.mjs *.png   # render-quality gate, standalone
```

### `rendercheck.mjs` — read before trusting any render result
The original gate was "PNG ≥ 2000 bytes **and** two frames hash differently". That accepts broken
output: a partial render with flat fills is large and does change between frames. The current gate
decodes each frame to raw RGB via ffmpeg and measures **distinct colours**, **dark fraction** and
**dominant-colour share**. Calibration on this set: working renders 132–268 distinct colours; the two
broken ones scored 55 and 57.

### Do not `import` from `orrery.mjs`
It has top-level executable code alongside its exports — importing it re-runs the entire five-model
benchmark as a side effect, and on a shell without `ANTHROPIC_API_KEY` it will overwrite `scores.json`
with failed Opus rows. `ornith-retry.mjs` reads `orrery-prompt.txt` instead.

---

## data/

- `results.csv` — 95 rows across eight experiments, tagged `valid` / `INVALID` / `LOWER_BOUND` /
  `derived`. Invalidated runs retained on purpose.
- `environment.json` — machine-captured hardware and toolchain snapshot.
- `gotchas.md` — trap catalogue in source form.

## scripts/

PowerShell behind No.11: the llama.cpp CUDA build, the tuned launch config, and every sweep
(draft width, reasoning effort, context size, filled context, prompt shape, Ornith).

---

## Caveats to carry into publication

1. **Orrery visuals are not scored.** All five satisfied every stated requirement and all five render
   and animate. Which looks best is subjective and left to the reader.
2. **Ornith is scored 60% on the orrery, not 100%** — it needed two attempts. The 100% column records
   that a second sample succeeded; it is not the score.
3. **Creative writing is excluded from every aggregate.** Rubric-scored by Claude while three of five
   entrants are Claude models. Constraint adherence is machine-checked; craft is not.
4. **Coding tasks are JavaScript**, because Node was the only real runtime on the box and objective
   grading requires execution. Mildly favours JS-strong models.
5. **The agentic result rests on a single spatial world.** Evidence about state tracking across turns,
   not a general verdict on tool use.
6. **No vendor-reported figure is mixed into any measured result.** Third-party numbers in No.12 are
   fenced and labelled as not comparable.
