Debugging
partly builtMissing: jadpo incident, trace, traces, metrics, logs, watch, call, test new --from, replay and mcp. See What is built.
Jadpo code is written mainly by coding agents and read by people, so two
jobs matter most. When something goes wrong, you or your agent need to get
from the symptom to the .jadpo line and the reason, without reading the
code Jadpo generates. And when an agent hands over a large change, you need
to see what it does to your app, such as who can now read which data,
before you read it line by line. This page covers both: where errors
point, how to see what a request did and why, and how to review a change.
The command line, the developer console and the agent tools (MCP) all show the same evidence. The compiler and the runtime record that evidence, and each view only displays it. If the console shows why a caller was refused, that's because the compiler and the runtime recorded the reason, not because the console worked it out.
| Tool | What it does |
|---|---|
Errors point at .jadpo |
Always a .jadpo file and line, in development and production |
| Production incidents | jadpo incident names the line in the build that failed, then where that code is now |
| Breakpoints | Not offered |
| Why the language decided something | jadpo why |
| What a request did | The request timeline in jadpo dev; jadpo trace <request id> |
| Watching code run | jadpo watch waits for a named part of the code to run and prints it |
| Provider calls in development | jadpo calls: every call logged with full values, in development only |
| Traces, metrics and logs in development | jadpo traces, jadpo metrics, jadpo logs, with filters, --follow and --json |
| Failing request to test | jadpo test new --from <request id> |
| Run a query or action | jadpo call <name> --as <user> |
| Developer console and MCP | A local web page and read-only agent tools over the same evidence |
| Reviewing a change | A report with behaviour first, and a static web view of it |
| JSON for agents | Every command and view (Tools for agents) |
| Coverage by path | Tests and production compared path by path |
| Production in review | The approval report shows traffic and failures on the paths a change touches |
| Replaying a production request | Opt-in recording of what each effect returned, replayed locally |
| Query cost of a change | Queries added or removed per path, in the approval report |
Most of this isn't built yet; What is built says which parts are.
A request in jadpo dev
jadpo dev runs your app and prints one line for each request, with its
request id, its status and how long it took, so it is where most debugging
starts. Here is a small app with one route, which stores nothing and which
anyone may call:
domains/todos/routes/todos.jadpo:
use todos/types { NewTodo, TodoView }use todos/actions { add_todo }/// The todo list.routes Todos { prefix: /todos /// Adds a todo. POST / { authentication: RouteAuthentication.none input: NewTodo output: TodoView run: add_todo(input) }}
domains/todos/types/new_todo.jadpo:
/// What a caller sends to add a todo.type NewTodo = Input { title: Text}
domains/todos/types/todo_view.jadpo:
/// A todo, as the app sends it back.type TodoView = Output { title: Text done: Bool}
domains/todos/actions/add_todo.jadpo:
use todos/types { NewTodo, TodoView }/// Builds the todo and sends it back. It stores nothing.action add_todo(input: NewTodo) -> TodoView { return TodoView { title: input.title done: false }}
policy.jadpo:
use todospolicy { actions: { todos.add_todo: [Access.public] }}
RouteAuthentication, Access, Text and Bool are built into Jadpo, and
every other name is declared here. Run jadpo api update once, then
jadpo dev, and send it two requests:
curl -X POST http://localhost:3000/todos \ -H 'content-type: application/json' -d '{"title": "Buy milk"}'curl -X POST http://localhost:3000/todos \ -H 'content-type: application/json' -d '{"title": 5}'
$ jadpo devjadpo dev, started 02:47:52listening on http://localhost:3000 routes 2 routesserving: saves reload, press ctrl-c to quitreq_4035 POST /todos 200 6 ms 127.0.0.1req_beb8 POST /todos 422 invalid_input 0 ms 127.0.0.1
The second title isn't text, so the app refused it with a 422 and said why.
Its line shows the start of the request's id, which the caller also has in
the x-request-id header and an error's request_id, so a report from a
caller leads to the line.
| Errors point at the .jadpo line Every stack, log event and error response that names a place names a |
| The request timeline in jadpo dev
|
| Watching code run: jadpo watch not built Not built yet. |
| Provider calls in development: jadpo calls In |
| Traces, metrics and logs in development not built In development, your app's telemetry, its traces, metrics and logs, stays on your machine (Telemetry). |
| Capturing a failing request as a test The quickest reliable fix starts by reproducing the bug. |
| Running a query or action: jadpo call Not built yet. |
| jadpo why: why the language decided something Much of what surprises people in Jadpo is a decision the language made for them: policy hid a record, a lifecycle filtered it out, a subscriber didn't run, or a cache answered. |
| Production incidents after the code has changed not built By the time you look at a production failure, the code may have moved on. |
| Breakpoints and stepping You can't set a breakpoint in a |
| The developer console and MCP not built The same evidence is also there as a web page, and as tools for an agent that can't run commands. |
| What the graph and production evidence add not built Each of these joins the compiler's graph to path IDs. |
What is built says which of this works today.
Markdown for agents: /docs/debugging-and-review.md.Built from Jadpo main at aee2e8f.