---
name: eta-tables
description: The canonical ETA table format for reporting status on long-running autonomous work. Use whenever reporting progress on parallel agents, build waves, or any multi-step job where the user needs to know what is running, what is blocked, and when each thing lands. Post one every status update — never a prose-only status.
version: 1.0.0
updated: 2026-08-14
---

# ETA Tables

The standard status artifact for autonomous and long-running work. One table, every report, no exceptions.

## Why this format

A status update has to answer three questions at a glance, on a phone, without scrolling: **what is running, what is stuck, and when will it be done.** Prose buries all three. A table with a fixed column order puts them in the same place every time, so the reader learns where to look once and never re-reads a layout.

The emoji are load-bearing, not decoration — they let someone scan the Phase column and find ⛔ and ⚠️ without reading a single word.

## The format

Lead with a single line naming the time the table was recorded:

```
ETA table — 3:47pm MT
```

Then a markdown table with **these five columns, in this order**:

| ETA | MT | Phase | Item | Rubric |
|---|---|---|---|---|
| ~2h 15m | 9:45am | 🔨build | **7-28-0001 w16-fillrate** — chunking A/B re-run | Single-call vs chunked run live on all 3 tenants; both fill rates pasted; winner kept. Done when the losing strategy is reverted in code. |
| ~45m | 8:15am | 🎨assets | **7-28-0002 w16-photos** — hero evidence | Every tenant hero is a real photo or an honest themed fallback; asset inventory pasted; 0 broken images in a 1440x900 + 390x844 contact sheet I open myself. |
| ✅ | 7:26am | ✅done | **7-28-0003 cron** — hourly @ :23 | `CronList` shows the job; a fired run posts a table in this exact format. Verified by me. |
| — | — | ⛔blocked | **7-28-0004 admin/staff** — 6 mock pages vs 123 views | Unblocks on Steve's architecture call. Done when a prospect can walk ≥15 admin views branded to the tenant, captured as a 1-sec screen-flow contact sheet. |
| — | — | ⚠️stalled | **7-28-0005 suite customizers** — 7 orphaned | Done when `grep` shows every suite has a caller and the registry reports bespoke-vs-generic counts. |

### Column headers are `ETA` and `MT` — short on purpose

Not "Relative ETA" and "Mountain Time". Short headers let the table **collapse correctly on narrow screens and in chat clients**. The two time columns are the ones that get squeezed first, and long headers force wrapping that destroys readability on a phone. `ETA` and `MT` are unambiguous in context.

### Every Item starts with a dated index ID

Format: **`M-D-NNNN`** — month, day, then a zero-padded four-digit counter. `7-28-0001` is the first item worked on 28 July; `7-28-0002` the second, counting up to `7-28-9999`. The counter is **per day, per project**, and resets each day.

The ID goes at the very start of the bolded item name, before the descriptive text:

```
**7-28-0017 w22-mobile** — 390px gallery, hero logo contrast
```

Why: it gives every piece of work a stable handle that can be referenced across days, tables, commits and conversations without ambiguity. "Where did 7-28-0017 land?" is answerable; "where did the mobile thing land?" is not. Once an ID is assigned to a task it **never changes**, even as the task's phase, ETA or description evolves — carry the same ID fire after fire until the item is done or dropped.

### The Rubric column — how we will know it is actually done

Every row carries a rubric. It states, concretely:

1. **The success case** — what is true when this is finished.
2. **The measurement** — the specific check that decides it. A grep count, a test name, a measured pixel value, a reviewer verdict. Not "looks good".
3. **The user flow or end-to-end UI test** that proves it, verified with **screenshots and contact sheets** — screen-flow recordings captured **every one second** — so the claim rests on pixels a human can inspect, not on an agent's report.

A rubric written before the work starts is a contract; written afterwards it is an excuse. Write it when you add the row.

Bad rubric: *"gallery looks better on mobile."*
Good rubric: *"At a verified 390px viewport, every gallery card ≥300px wide with a legible label; measured rects pasted; failing-then-passing test output shown; 1-sec contact sheet of the scroll opened and described."*

## The rules

1. **Every row gets BOTH times.** A relative ETA (`~2h 15m`) and an absolute local time (`9:45am`). Relative alone makes the reader do math against an unknown "now"; absolute alone hides how long the wait is. Rows that are done or blocked use `✅` / `—` in place of a time.
2. **12-hour local time, lowercase meridiem.** `3:47pm`, never `15:47`. Default to the user's timezone; the `MT` header is America/Denver — swap the header if the user is elsewhere (`ET`, `PT`, `UTC`).
3. **One row per running agent, and one row per pending task.** Not one row per phase. If five agents are running, that is five rows. The table is an inventory, not a summary.
4. **Blocked and stalled rows stay in the table.** Do not drop them because they are not progressing — that is exactly the information the reader needs most. Carry them fire after fire until they resolve.
5. **Bold the item, ID first, then an em-dash, then what it is doing.** `**7-28-0017 w16-fillrate** — chunking A/B re-run`. Scannable left edge.
6. **Sort by what the reader cares about**, not chronologically: done items near the top if they just landed, then in-flight by soonest, then queued, then blocked/stalled at the bottom.
7. **Never fabricate an ETA.** If you do not know, say `unknown` and why. A wrong ETA is worse than an absent one because it gets planned against.
8. **Every row carries an ID and a rubric.** No exceptions, including blocked and stalled rows — a blocked item still needs a stated success case, or nobody can tell when unblocking it worked.
9. **IDs are immutable and sequential per day.** Never renumber, never reuse. If a task spans days it keeps its original ID.

## Phase vocabulary

Use exactly these. Do not invent new ones — a fixed vocabulary is what makes the column scannable.

| Emoji | Phase | Meaning |
|---|---|---|
| ⚪ | queued | Defined and ready, not yet started |
| 🔨 | build | Writing code |
| 🧪 | test | Running tests, verification suites, twins review |
| 🎨 | assets | Images, media, design system, screenshots |
| 🌐 | E2E | End-to-end runs, browser captures, live URL checks |
| 🚀 | deploy | Shipping, republish signals, dashboard actions |
| ✅ | done | Complete AND independently verified |
| ⛔ | blocked | Cannot proceed — needs a decision, a credential, or a human action |
| ⚠️ | stalled | Should be moving but is not — crashed, killed, or drifting |

## ✅ means verified, not reported

A row is only ✅ when **you personally checked it** — opened the screenshot, grepped for the callers, probed the URL, read the test output. An agent reporting success is not verification. This distinction is the entire value of the table; the moment ✅ means "someone claimed it", the table becomes decorative.

If something is done but unverified, it is still 🔨 or 🧪. Say so.

Every build-wave row remains in build, test, or E2E while its own wave re-reads the original human prompt,
phase-0 story, and final specification; captures and self-scores the real flow against both; validates distinct one-second frames; and
runs regressions. Capture is not a separate later wave. A failed capture, missing receipt, or twin
`FAIL` returns the item to the keeper's bounded rework loop.

**Operative machine gate:** Before emitting `✅done`, run
`node skills/tutorial-verified-done/scripts/check-evidence-receipt.mjs docs/evidence/receipts/<item-id>.md`;
the command must exit `0`, which proves the receipt exists, conforms to the canonical
[evidence receipt schema](../tutorial-verified-done/references/evidence-receipt-schema.md), and
contains two clean-context twin `PASS` verdicts over the exact same evidence paths. Any other exit
keeps the item non-done; no agent judgment may override this file check.

## Anti-patterns

- **Prose status with no table.** Even for a one-line update, post the table.
- **Dropping the table when the news is bad.** Bad news is when it matters most.
- **Collapsing several agents into one row** to make the table look tidier.
- **A ⛔blocked row with no owner.** Say what unblocks it and who has to do it — "needs your billing dashboard" beats "blocked on quota".
- **Long column headers.** They break the mobile collapse. `ETA` and `MT`.

## Companion practice

Pair every table with a short honest narrative above or below it — what you verified yourself, what surprised you, what you got wrong. The table carries state; the prose carries judgement. See also: [[honest-grading]], [[build-waves]], [[real-user-verification]].

When a real product tracker exists, use stable phase, worker, and step keys and project state idempotently from the canonical lifecycle. Show every transition, blocker, error, check result, commit handoff, evidence boundary, and terminal notification. Never invent a tracker job or maintain a parallel status fiction. No row may show `✅done` until all four narrated tutorial variants, four audio-derived transcripts, four one-second contact sheets, served-artifact identity, and byte-pinned clean-context twin verdicts pass against every phase-0 user-story step. The schema-valid evidence receipt at `docs/evidence/receipts/<item-id>.md` is the machine-readable proof of that state. Nothing less counts.
