# One-shot test: Three-point area lighting, a physical sky and Cycles

Test `oneshot-mini-lighting`: one message per side with no reference image, then nothing; model claude-opus-5-5, runtime claude, effort low; finished 2026-10-15T08:48:14+0900. Limits: 300 s for the turn, 3 USD at list prices.

## Result

| Side | Verdict | Closed checks | Pixel checks | Stop reason |
| --- | --- | --- | --- | --- |
| Blender MCP (Claude Code) 1 | FAILED | 4 / 5 | none asked | finished |
| Blender MCP (Claude Code) 2 | FAILED | 4 / 5 | none asked | finished |
| Blender MCP (Claude Code) 3 | FAILED | 4 / 5 | none asked | finished |
| Blender MCP (Claude Code) 4 | PASSED | 5 / 5 | none asked | finished |
| Blender MCP (Claude Code) 5 | FAILED | 4 / 5 | none asked | finished |
| Angelo 1 | PASSED | 5 / 5 | none asked | finished |
| Angelo 2 | PASSED | 5 / 5 | none asked | finished |
| Angelo 3 | PASSED | 5 / 5 | none asked | finished |
| Angelo 4 | PASSED | 5 / 5 | none asked | finished |
| Angelo 5 | PASSED | 5 / 5 | none asked | finished |

A side passes only when it ended its one turn by itself and every closed check and pixel check passed. No score judged by a model is counted.

This test asks for no still, so it has no pixel check; it starts from the factory scene and does not ask for it to be cleared.

## How each side got there

| Path metric | Blender MCP (Claude Code) 1 | Blender MCP (Claude Code) 2 | Blender MCP (Claude Code) 3 | Blender MCP (Claude Code) 4 | Blender MCP (Claude Code) 5 | Angelo 1 | Angelo 2 | Angelo 3 | Angelo 4 | Angelo 5 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Verdict (closed checks only) | failed | failed | failed | passed | failed | passed | passed | passed | passed | passed |
| Closed checks passed | 4 / 5 | 4 / 5 | 4 / 5 | 5 / 5 | 4 / 5 | 5 / 5 | 5 / 5 | 5 / 5 | 5 / 5 | 5 / 5 |
| Messages typed | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Stop reason | finished | finished | finished | finished | finished | finished | finished | finished | finished | finished |
| Model requests | 4 | 4 | 4 | 4 | 4 | 1 | 1 | 1 | 1 | 1 |
| Rounds | 4 | 4 | 4 | 4 | 4 | 1 | 1 | 1 | 1 | 1 |
| Tool calls, by tool | 3: execute_blender_code 2, ToolSearch 1 | 3: execute_blender_code 2, ToolSearch 1 | 3: execute_blender_code 2, ToolSearch 1 | 3: execute_blender_code 2, ToolSearch 1 | 3: execute_blender_code 2, ToolSearch 1 | 2: StructuredOutput 1, angelo_scene_program 1 | 2: StructuredOutput 1, angelo_scene_program 1 | 2: StructuredOutput 1, angelo_scene_program 1 | 2: StructuredOutput 1, angelo_scene_program 1 | 2: StructuredOutput 1, angelo_scene_program 1 |
| Mutations: typed calls / script calls (typed share) | 0 / 2 (0 %) | 0 / 2 (0 %) | 0 / 2 (0 %) | 0 / 2 (0 %) | 0 / 2 (0 %) | 1 / 0 (100 %) | 1 / 0 (100 %) | 1 / 0 (100 %) | 1 / 0 (100 %) | 1 / 0 (100 %) |
| Scripts by category | render_world 2, camera_lighting 1, materials 1 | render_world 2, camera_lighting 1, materials 1 | render_world 2, camera_lighting 1, materials 1 | render_world 2, camera_lighting 1, materials 1 | render_world 2, camera_lighting 1, materials 1 | none | none | none | none | none |
| Why each script (from the request's own steps) / scripts that raised | – | – | – | – | – | none / 0 | none / 0 | none / 0 | none / 0 | none / 0 |
| Each mutation in order | script (render_world); script (materials, camera_lighting, render_world) | script (render_world); script (materials, camera_lighting, render_world) | script (render_world); script (materials, camera_lighting, render_world) | script (render_world); script (materials, camera_lighting, render_world) | script (render_world); script (materials, camera_lighting, render_world) | typed angelo_scene_program (5 ops) | typed angelo_scene_program (5 ops) | typed angelo_scene_program (5 ops) | typed angelo_scene_program (5 ops) | typed angelo_scene_program (5 ops) |
| Lookups before the first change, by tool | 1: ToolSearch 1 | 1: ToolSearch 1 | 1: ToolSearch 1 | 1: ToolSearch 1 | 1: ToolSearch 1 | 0 | 0 | 0 | 0 | 0 |
| Capability lookups / lookup rounds / rejected plans | – | – | – | – | – | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 |
| Approvals asked / approved / declined | no approval gate | no approval gate | no approval gate | no approval gate | no approval gate | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 |
| Seconds waited on approvals | – | – | – | – | – | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| Declined by the harness's approval policy (not a product failure) | – | – | – | – | – | none | none | none | none | none |
| Errors: total / recovered in the turn / ended the turn | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 | 0 / 0 / 0 |
| Looked at an image of its own result | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 | 0 image(s); reached the model: 0 |
| Looked at its result after its last edit | no | no | no | no | no | no | no | no | no | no |
| Rendered in the turn | no | no | no | no | no | no | no | no | no | no |
| Saw its final render | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown | unknown |
| Time to first visible activity, s | 2.57 | 2.74 | 3.15 | 2.5 | 2.44 | 8.61 | 9.52 | 6.79 | 7.86 | 10.37 |
| Wall time, s | 18.72 | 18.81 | 21.27 | 17.83 | 19.09 | 8.66 | 9.59 | 6.84 | 7.92 | 10.42 |
| Tokens in (of which cached) / out | 149002 (123072) / 1488 | 148928 (139206) / 1437 | 148882 (139206) / 1442 | 148887 (139206) / 1322 | 148918 (139223) / 1468 | 36211 (34543) / 799 | 36212 (34543) / 758 | 36210 (34543) / 651 | 36210 (34543) / 709 | 36212 (34543) / 753 |
| Output tokens | 1488 | 1437 | 1442 | 1322 | 1468 | 799 | 758 | 651 | 709 | 753 |
| Cost at list prices, USD (runtime's own estimate) | 0.184 (0.2617824) | 0.1052 (0.1343252) | 0.1051 (0.13405720000000002) | 0.1027 (0.13169720000000001) | 0.1057 (0.13473259999999998) | 0.0362 (0.036225) | 0.0354 (0.035413) | 0.0333 (0.033257) | 0.0344 (0.034417) | 0.0353 (0.035313) |

Angelo 1. Intended path: one message: yes (1 typed); error-ended turns: 0 (stop reason: finished); mutations by typed tools: 100 % (1 of 1 calls); checks passed: 5 of 5.

Angelo 2. Intended path: one message: yes (1 typed); error-ended turns: 0 (stop reason: finished); mutations by typed tools: 100 % (1 of 1 calls); checks passed: 5 of 5.

Angelo 3. Intended path: one message: yes (1 typed); error-ended turns: 0 (stop reason: finished); mutations by typed tools: 100 % (1 of 1 calls); checks passed: 5 of 5.

Angelo 4. Intended path: one message: yes (1 typed); error-ended turns: 0 (stop reason: finished); mutations by typed tools: 100 % (1 of 1 calls); checks passed: 5 of 5.

Angelo 5. Intended path: one message: yes (1 typed); error-ended turns: 0 (stop reason: finished); mutations by typed tools: 100 % (1 of 1 calls); checks passed: 5 of 5.

## Over the trials

Each cell after the pass count is the median over the side's trials, then the least and the most in brackets. One trial is a sample of one: read a difference between sides against these ranges.

| Side | Passed | Seconds | Output tokens | Typed share of mutations | Lookups before the first change | Cost, list USD | How the turns ended |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Blender MCP (Claude Code) | 1 of 5 | 18.8 [17.8-21.3] | 1442 [1322-1488] | 0 % [0 %-0 %] | 1 [1-1] | 0.1052 [0.1027-0.184] | finished 5 |
| Angelo | 5 of 5 | 8.7 [6.8-10.4] | 753 [651-799] | 100 % [100 %-100 %] | 0 [0-0] | 0.0353 [0.0333-0.0362] | finished 5 |

## Why a side did not pass

- **Blender MCP (Claude Code) 1**: check failed: three area lights on the cube: key, fill and a rim behind it
  - three area lights on the cube: key, fill and a rim behind it: {"lights": [{"name": "Key_Light", "energy": 1000.0, "aim_dot": 1.0, "behind": false, "reach": 17.544}, {"name": "Fill_Light", "energy": 300.0, "aim_dot": 1.0, "behind": false, "reach": 6.977}, {"name": "Rim_Light", "energy": 700.0, "aim_dot
- **Blender MCP (Claude Code) 2**: check failed: three area lights on the cube: key, fill and a rim behind it
  - three area lights on the cube: key, fill and a rim behind it: {"lights": [{"name": "Key_Light", "energy": 1000.0, "aim_dot": 1.0, "behind": false, "reach": 17.544}, {"name": "Fill_Light", "energy": 300.0, "aim_dot": 1.0, "behind": false, "reach": 7.453}, {"name": "Rim_Light", "energy": 800.0, "aim_dot
- **Blender MCP (Claude Code) 3**: check failed: three area lights on the cube: key, fill and a rim behind it
  - three area lights on the cube: key, fill and a rim behind it: {"lights": [{"name": "Key_Light", "energy": 1000.0, "aim_dot": 1.0, "behind": false, "reach": 17.544}, {"name": "Fill_Light", "energy": 300.0, "aim_dot": 1.0, "behind": false, "reach": 7.453}, {"name": "Rim_Light", "energy": 800.0, "aim_dot
- **Blender MCP (Claude Code) 4**: passed.
- **Blender MCP (Claude Code) 5**: check failed: three area lights on the cube: key, fill and a rim behind it
  - three area lights on the cube: key, fill and a rim behind it: {"lights": [{"name": "Key_Light", "energy": 600.0, "aim_dot": 1.0, "behind": false, "reach": 14.634}, {"name": "Fill_Light", "energy": 200.0, "aim_dot": 1.0, "behind": false, "reach": 7.619}, {"name": "Rim_Light", "energy": 450.0, "aim_dot"
- **Angelo 1**: passed.
- **Angelo 2**: passed.
- **Angelo 3**: passed.
- **Angelo 4**: passed.
- **Angelo 5**: passed.

## The brief

Sent once to each side, unchanged (SHA-256 a8599e984a8f8585f27cec4efb8d6e43e0414b1aaa99f782dbb9ead71dbd524d):

> Light the cube with a key, a fill and a rim area light, set the world to a physical sky with the sun 5 degrees up, and switch to Cycles at 128 samples with denoising.

## References

None: the message is text only.

## What the other side's client was allowed

- every tool of the Blender MCP server (model-written Python included, unrestricted)
- Claude Code's Read tool on image files anywhere, and its read-only file tools in its working folder and in the trial folder (stock Blender's working and temporary folder): it can open the images it rendered
- the reference images also as files in its working folder
- anything else that would prompt (shell, edits, web) is denied and counted: nobody answers prompts

## Not recorded

Shown as "unknown" above, and what records each:

- `angelo.final_render_seen`: whether the agent saw the still it rendered: recorded by add-ons whose job records carry a shown mark; without it only a job-rendered still is known (not seen inside the turn)

## Opinion (never counted)

No model-judged comparison was run. People judge the pictures in `oneshot-report.html`.

