# Grade Lab

Status: In progress

An agent grades my underwater footage directly inside DaVinci Resolve, remembers my verdicts and turns them into rules.

GoPro log footage goes in. The grade lands on real Resolve nodes I can open and keep editing. Every word of feedback is saved against the exact version it was about, so the next shot starts from a grade I already loved.

- Role: Solo builder, directing coding agents
- Stack: Python, NumPy, DaVinci Resolve 21.1, DCTL, Fusion Fuses, MCP
- As of: Oct 2026 ledger
- Scale: 100+ MCP tools and one 20-node master
- Verdicts: 133 on 26 shots
- Commits: 1,263 on this Mac since Sep 29
- Showcase repo: https://github.com/henryhcooperr/grade-lab

[Rebuild] Grade Lab’s review page comparing camera log and the graded frame of a garibaldi at Catalina. A rebuild of the review page I grade in, not a screen capture. The frames are real: twelve from the Garibaldi shot at Catalina, camera log on A and my grade on B. A screenshot of the real page is at the end.

## Resolve lets agents in. Its color page barely does.

Resolve has a scripting API, so an agent can get in. On the color page that API reaches very little: apply a saved grade (`ApplyGradeFromDRX`), set a CDL (`SetCDL`), load a LUT (`SetLUT`), and switch nodes on and off (`SetNodeEnabled`).

So Grade Lab works through those few doors. The agent corrects the other nodes, turns them on and off when a shot needs it, and reads every write back before it counts. Everything else needed a way around.

## What the scripting API can’t reach

The API can’t → So Grade Lab:

- Add or wire nodes, or a parallel mixer: Builds the 20-node master once, by hand, saves it as a native PowerGrade with a DRP backup, and applies it to each clip as a DRX still.
- Add a creative look: Writes each look as a DCTL program, because `SetLUT` accepts one, and loads it on node 14.
- Set an effect’s strength: Keeps a pinned DRX still for each UltraSharpen amount, and edits saved grades offline for the rest.
- Draw a window or qualifier: Leaves them to me, authored by hand in the master.

## Decisions

### Real nodes, so I can keep going by hand

Exporting a LUT would have been easier. I wanted the agent working on the same node graph I’d grade by hand, so I can open any version in Resolve and keep going. Every clip gets the same 20-node master, and each node has one job.

Instead of exporting a LUT.

[Rebuild] A 20-node Resolve editor with node 5, Base CDL, selected. A rebuild of Resolve’s Color page node editor, not a screen capture. The 20 nodes, their order and what the agent can reach come from the Grade Lab master and its tools.

[Rebuild] Eight stage tabs above a shot, stepping from camera log to verdict. Eight stages, from the camera’s log to my verdict. Each one runs on its own nodes.

### Offline edits, proven in Resolve itself

Grade Lab edits Resolve’s saved grade format directly, and the edits are byte-exact. One changed 9 bytes of a 1,162-byte grade and left every other byte identical. UltraSharpen, UltraNR and Dehaze transplant from donor grades with their settings intact.

Each edit is proven in Resolve: import into a fresh lab project, save, reopen, render native 16-bit frames. On the Dehaze transplant, the reopened pixels matched exactly.

Instead of assuming a write landed.

### My words stay bound to the exact version

On cut 30, V0128 got “i guess it does become pink tho and the divers leg does look worse.” V0129 got “looks great.” Those are my exact words, saved against that shot and that version.

That “looks great” is bound to the surface-fix version, so it doesn’t sign off the fin or the leg.

Instead of feedback that disappears with the chat.

[Rebuild] Cut 30’s versions V0128 and V0129 with my comments and a wipe between them. The frames are real renders of cut 30. The quotes are my exact words from the Grade Lab ledger, retold as a timeline.

### The next shot starts from a grade I praised

When a new shot comes in, Grade Lab ranks past grades by how alike the camera signal looks, then lifts the ones I praised: `Score = e^(−d) × (1 + max(0, o))`. `d` is the distance between two shots’ camera fingerprints over 17 keys. `o` is the outcome of my feedback on that version, which fades with a 21-day half-life.

It’s case-based retrieval, not a trained model, and a better starting point is not automatically a better final image.

Instead of averaging my past grades.

[Rebuild] Cut 32’s ranked past grades, starting from cut 30 at 0.9436. A recorded replay of the real ledger, fixed to Oct 10, 2:26 PM. The loop switches my feedback off and on. Shot 31 keeps the same starting point either way, which is part of the result.

## How it’s built and checked

The agent gets one route through the tools. Each tool’s reply says what comes next, and each record it writes is bound by sha256, so nothing gets hand-edited along the way.

[Rebuild] A terminal-style list of Grade Lab’s tools in order, with one line of result under each. One clip’s walk as it reads in an agent session, not a captured log. Tool names are the MCP server’s own; the line under each says what that tool returns.

- Lab copies only: Never on my own project. A DRP backup goes in before the first change.
- Crashes: Stop at the first one.
- Approval: A passed check is not approval. Only my words are.

## Where it stands

### Works today

- 133 verdicts on 26 shots, each bound to its version.
- 21 of the 26 shots reached a grade I praised within three versions.
- Depth-aware Sea-thru restoration on Resolve’s Depth Map, opt-in for the shots that deserve it.

### In progress

- Replay proof is built but hasn’t been exercised yet.
- 125 of the 133 verdicts haven’t been reflected into lessons yet, and a lesson only becomes a rule with my yes.

[Screenshot] Grade Lab’s real review page. The real review page, for comparison with the rebuild at the top.

Next: Social Lab, /work/social-lab/

Back to the homepage: /
