ChartnautDocs

Definition authoring agent

The definition builder's agent writes and edits one definition: its events, the emits with their labels, what it draws, and every file of a multi-file package. Its edits apply straight to the draft, and the chart beside the chat reloads with each one.

Ask it to mark a setup in history. Measuring what happened after the setup is a study.

How an edit lands

The agent sends a set of file patches with apply_flow_edits: create, replace, delete, or an exact edit of part of a file. Every patch set saves to the draft, even one that does not link or derive; the result names the file and line that failed, and the agent fixes it with another edit. A Files updated message in the chat confirms each one.

The only thing it asks you first is using an indicator from the library, with an Indicator proposal card.

Its loop on every change

  1. Read the definition with get_flow_state and its files with get_flow_files.

  2. Save the patch set with apply_flow_edits.

  3. Lint with lint_flow and typecheck with typecheck_flow. Both read the saved draft. Typecheck is what catches a ctx.emit of an event id that was never declared, a misspelled ctx.params.<id>, or an output id that does not exist.

  4. Dry-run with dry_run_flow: the same pipeline a run over history uses, over a preset market, keeping events in memory.

  5. Check the builder's chart with wait_for_preview and inspect_preview, and read ctx.log output with get_flow_logs.

It stops after three failed lint attempts on the same problem instead of resubmitting the same edit.

Tools

Tool

Runs in

Does

get_flow_state

Server

The saved definition row

get_flow_files

Browser

The live draft: every file, its role and which is the entry

apply_flow_edits

Browser

Saves a patch set; returns runnable, link and derive errors, and a bench verdict for layers

lint_flow

Browser

Links the draft's imports, derives the manifest and lints: {ok, issues:[{rule, severity, message, path, line}]}

typecheck_flow / read_flow_dsl

Browser

Typechecks against the DSL's real declarations; reads those declarations

dry_run_flow

Server

Runs the saved draft over a preset market. Returns events (first 200), events_total, emits_by_event, dependencies, warnings, failures and logs

bench_layer / dry_run_layer_paint

Server

Runs a layer's layout and paint and grades or measures them

wait_for_preview / inspect_preview / get_flow_logs

Browser

Reads what the builder's chart calculated and logged

search_indicators / resolve_dependency_contract / request_add_indicator

Server, browser

Finds a dependency, its exact accessor keys and version, and asks you to add it

update_title

Server

Names the definition on your first message, and renames it when its purpose changes

What it checks before it calls a change done

  • The entry file has meta(...) and export function onBar(ctx); no other file has either. Helpers use relative imports with the extension, such as ./lib/levels.js. imports.use({ flowId, alias }) is only for another definition's events.

  • meta({ kind: "flow" }), since events are refused on kind: "indicator".

  • Every ctx.emit names a declared event and passes a non-empty label. Every payload field has a type and a plain-English description, because study agents read them.

  • Events are visible unless you asked otherwise: no paint: "none".

  • Dedupe uses oncePer: { keys } on the event, never a set kept in ctx.accum.

  • Every drawing call has an outputs.declare of the matching kind. Every hline and range output sets mode explicitly; invalidateOnCustomFunction has an invalidateWhen; invalidateOnEvent names declared event ids.

  • Zones or levels an indicator already computes are read from it, through lifecycle({ outputId, at: ctx.time }) for ranges, not rebuilt in the definition.

  • Sessions come from ctx.session({ period, open, close, tz }), never bar counts or fixed UTC offsets.

  • Nothing emits or draws inside a timeframe handler; one-shot emits gate on handle.closedThisBar.

  • Every dependency pins the version the search or approval returned.

Asking well

  • "Emit or_break with the label OR break ↑ when the close crosses the opening-range high, once per session."

  • "Move the classification helpers into ./classify.js; keep meta and onBar in the entry file."

  • "Add a subtitle with the range in percent and the sample size, two values at most."

Requests it cannot do: publish a study table (use the study builder), skip labels (they are required), or import npm packages (only relative imports work).