CodeHerderSearch⌘KRequest access →

Stage-attempt detail

Go from a stage's acceptance rate down to the individual attempts behind it, and learn what every column of the attempt table means.

Stage signals counts attempts and gives you a rate per stage. Sooner or later that rate raises a question it can’t answer itself: which attempts were those? ch quality attempts lists them one per line, with the task, the stage, which try it was, how it turned out, what setup ran it, and what it cost.

Reach for it when a stage’s numbers look wrong and you want to see the rows rather than the average.

Where to find it

There’s no web-app page for this report. It’s CLI and API only.

ch quality attempts

Pass a workspace name, slug, slug path, or full ID as the first argument to scope it elsewhere; without one, the command uses the workspace the CLI is pointed at. Add --json for the raw data instead of the table. The report always covers exactly the workspace you asked for, with no cascade into child workspaces.

Any member of the workspace can run it. There’s no extra role or plan requirement.

The window flags are the ones stage signals uses: --window today|yesterday|week|month, or --since with a duration (3d, 12h) or an RFC 3339 timestamp. The two are mutually exclusive. Without either, the report covers the last 90 days. An attempt lands in the window by when it ended, not when it started.

What one row is

A row is one attempt: one go at one stage of one task. The count works the same way it does for stage verifications — attempt 1 is the first time the task entered that stage, attempt 2 is the try after work came back for rework, and so on. A task that gets parked and resumed at the same stage doesn’t start a fresh attempt.

A row appears once the attempt ends, which is the moment the task leaves the stage. An attempt still in progress isn’t listed yet.

What each column means

Column What it tells you
TASK The first eight characters of the task’s ID, for scanning. Tasks created around the same time can share this prefix, so don’t treat two matching TASK values as proof they’re the same task — use --json, which carries the full ID, when you need to be sure.
STAGE The workflow stage this attempt ran at.
ATTEMPT Which try this was at that stage.
OUTCOME accepted, reworked, pending, or censored — the same four buckets stage signals counts.
ARM A short fingerprint of the setup that ran the attempt, covering the coding-agent CLI, the model, the reasoning-effort setting, the launch config, the stage’s own prompt, and the skills loaded. Reads - when no single setup can be named — either CodeHerder couldn’t pin one down, or more than one setup touched the attempt.
GATES How many of the attempt’s stage verifications came back fail or error, as N failed. A dash means none did.
EFFORT What the attempt cost in model spend, in dollars. A dash means the spend hasn’t been attributed to it yet.
JUDGE Reserved for independent scoring of an attempt. skipped is the normal reading — it means no independent scoring ran for that attempt, not that anything went wrong. - means no judge information was recorded at all. Scoring itself isn’t something you can switch on from the app or the CLI today, so neither value points to an action you can take.

Sample output, with made-up numbers:

TASK      STAGE   ATTEMPT  OUTCOME   ARM       GATES     EFFORT  JUDGE
019fcb24  code    1        reworked  a1b2c3d4  1 failed  $1.82   skipped
019fcb24  code    2        accepted  a1b2c3d4  -         $0.94   skipped
019fcb24  review  1        accepted  -         -         $0.11   skipped
019fd07b  verify  1        pending   c9d0e1f2  -         -       -

If the window holds no attempts at all, the report prints no attempts.

A row fills in over time

Two columns arrive later than the rest. CodeHerder writes the row the moment the attempt ends, then works out how the attempt turned out and what it cost on a later pass. Until that pass runs, the row’s OUTCOME can be blank and its EFFORT can read -.

So a handful of bare-looking rows at the recent end of the window is normal. If the same rows still look bare a day later, that’s worth asking about.

Comparing setups with the ARM column

Two attempts carrying the same ARM ran under the same setup, top to bottom. That makes ARM the column to compare on when you’re asking whether one configuration handles a stage better than another.

It’s a tighter grouping than the one ch quality arms uses. That report groups by coding-agent CLI, model, and stage prompt only, which is why its FULL-ARMS column can read higher than 1: several exact setups folded into one cell. When a cell there looks like a blend, come here and read the individual ARM values to see what it’s a blend of.

An attempt that more than one setup touched also reads - in ARM — the table can’t credit or blame a single setup either way, so it shows the same dash as an attempt whose setup couldn’t be identified at all. Stage signals leaves those attempts out of its counts entirely; here the row still appears, just with a blank ARM. --json is what tells the two apart — see “What –json adds” below.

Paging through the rows

The report pages rather than truncating. --limit caps a page at 50 rows by default, up to 200. When more rows are waiting, ch prints a hint naming the token that fetches the next page:

more results — re-run with --cursor <token>
ch quality attempts --since 7d --limit 100
ch quality attempts --cursor <token>

Rows come back grouped by task, then stage, then attempt number — not newest first. A task’s attempts stay together, which is what you want when you’re reading one task’s history, and worth knowing when you’re looking for the most recent thing that happened. This grouping is by the task’s full ID, not by the TASK column’s shortened prefix — if two tasks happen to share a prefix, their rows won’t be interleaved even though the table might make it look that way at a glance. Check --json if the ordering looks off.

See Paging through long lists for the paging conventions every ch list command shares.

What –json adds

The table shows eight columns; the JSON carries more per row. Among them: whether the attempt has been confirmed yet and how long that took, the gate’s own verdict on it, how many sessions worked it, counts of send-backs and escalations into it, a flag marking an EFFORT figure that undercounts because part of the window’s spend belongs to another stage, and a flag marking an attempt that more than one setup touched — the thing a blank ARM in the table can’t tell you by itself, since the same dash also covers a setup CodeHerder simply couldn’t identify.

ch quality attempts --json
  • Stage signals — the per-stage rates these rows add up to, and the four outcome buckets
  • How work flows — stages, stage gates, and the verifications the GATES column counts
  • Review debt — how the review queue itself is doing: latency, rework, and cost
  • Understanding costs — where model spend is reported in full
CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close