Agent lint and dry-run
Every agent checks its code before you see the result: lint for shape, typecheck for the values passed to the DSL, then a dry run that executes the saved script on real market data. This page lists the checks for each script type and what each one proves.
Read it when an agent reports a dry run, or when a card shows dry run notes.
The checks, in order
Each check proves one thing, and passing it says nothing about the next.
Check | Proves | Does not prove |
|---|---|---|
Lint | The script is shaped right: declarations, pairings, rules | That it runs |
Typecheck or derive | The calls are typed right, and the manifest (outputs, inputs, dependency pins, timeframes) is real | That it runs over data |
Dry run | It executes without errors on a preset market, dependencies included | That the numbers are right on your symbol and range |
Real run | The study ran over your events and range | How it looks on the chart |
You, looking at it | It draws where and what you meant |
No agent can see the rendered chart. Every result card lists that under Not checked.
What a dry run is
A dry run executes the script on the same pipeline its real run uses, over real bars from a preset market that has the data the script needs, such as BTC. A script that reads volume candles runs where volume candles exist. A dry run writes nothing: no events are stored, no scripts are installed, no data is collected.
Its job is to prove the script runs without errors. Its numbers come from the preset window, so they say nothing about your symbol or your range. For that, look at the chart, run the definition over your range, or run the study.
Declared dependencies run too, each at the version the script pins, on the same bars. A dependency that throws, an unknown slug or a pinned version that does not exist fails the dry run. The result lists every dependency and its status.
Per script type
Script | Builder's agent | The Agent | What the dry run executes |
|---|---|---|---|
Indicator |
|
| The indicator engine over the preset bars, dependencies first |
Definition |
|
| The pipeline a run over history uses, in memory, returning the events it would store |
Study | Automatic on every Study edit proposal |
| The study engine over the events its declared definitions produce on the preset bars |
Trade study | Automatic on every proposal |
| The study engine over six stand-in positions on the preset bars |
App |
|
| Every root of the saved app against real data |
The Agent's apply_edits also returns the lint and derive verdict of every edit, so a broken edit is caught on the write.
A definition that emits nothing in the dry run window is a warning, not a failure. A rare condition can be quiet over a few hundred bars. emit_dropped: unknown_event_id means the emit names an event that is not declared; emit_never_reached means the condition never fired in the window.
A trade study measures your trades, which no dry run can compute, so its dry run places stand-in positions of every shape: long and short, winners and losers, same bar, multi-day and still open. The result says the positions were stand-ins.
An app's dry run lists roots that wait on data nobody has collected as pending, and does not fail them. Collecting is metered, so it waits for you to press Collect and open in the preview. read_canvas_screen is the one check that sees whether a page drew, but an empty table still counts as drawn.
Proposal checks
Study, trade study and Forward Insight proposals are dry-run before the card appears. A fault sends the proposal back to the agent to fix. After three attempts the card reaches you with the faults the agent could not fix listed as dry run notes, marked in amber. Other notes, such as a definition that fired no events, are facts about the dry run window.
Layers
For a script with output.layer, the dry run adds layers[id] (row_count, live_count, sealed_count, has_paint, has_paint_gl, has_gesture, seal_mode) and a row tail per layer. Paint never executes in a dry run.
bench_layer runs the dry run first so the rows are real, then executes layout and paint at three bar spacings (2, 6 and 14 px per bar) and grades the result: verdict (pass, fail or skip), failed, warned, remedy and runs. The checks are painted (zero draws with rows present), opsPerPixelRow (more draws than pixel rows), subPixelShare (rects under 1 px), paintMs, nanCoords (draws with a NaN coordinate, which paint nothing), and outsidePane and escape hatches as warnings. A pass with warned entries still needs reading. Saving a script with a painted layer runs the same bench and reports the verdict with the save.
dry_run_layer_paint is the ungraded single-spacing form: op counts by kind, paintMs, outsidePane, the escape hatches used and any renderer error. Its viewport block paints again with the chart scrolled past the rows, which shows whether a layer draws when its rows are off screen. On the chart, inspect_preview include: ["layers"] reports rows per layer from the latest calculation plus the frame stats (paint_runs, avg_paint_ms, breaker_tripped, escape_hatches).
What every agent confirms before it calls a change done
Declarations match every emit, drawing call and publish.
Every
ctx.emithas a label.Cross-bar state lives in
ctx.accum, withwarmupdeclared.Every dependency is resolved, with a pinned version from a search or approval.
Lint and typecheck are clean, and the dry run is quoted as it came back, not as expected.
For a Forward Insight:
pin_cellis added beside the existing results, indexed only by scope dimensions.
Lint and error codes explains each rule, and Troubleshooting goes from a symptom to its fix.
