Estimate, status, incidents, budget — one thread, or the cost of a requirement is a feeling.
👋 Hi, I'm Anton — a software engineer working mostly in PHP/Symfony and Go, currently carving a live PHP monolith into Go services. This series is about the order the work happens in: a wish becomes requirements, requirements become a contract, the contract becomes tasks. This part is about the last link — the tracker task — and about what it has to carry before anyone can answer "what did that requirement cost".
Running notes live on my GitHub: github.com/brilliant-almazov. This is how I do it right now, with the price attached — maybe you already do it better, maybe you see it differently.
The thesis
The tracker here is not reporting and it is not ceremony. It is the only place where a requirement, a contract, a unit of executable work, a pull request and an acceptance decision sit on one thread, in an order you can walk in either direction.
That thread exists for exactly one question: what did this cost? Not "was everyone busy" — what one requirement cost, from the sentence someone said out loud to the change being accepted.
Without an estimate written before the work and a fact recorded after it, that question has no answer. It has opinions. "That one was expensive" and "that one was fine" become statements about how the week felt, and every argument about scope after that is an argument between two feelings.
The case: iterations that cost 350 000 tokens each
The concrete thing that made me build this rather than talk about it.
What happened. In one of the early prompt sets, each iteration was eating about 350 000 tokens. The tasks were being completed. Nothing was failing. The number simply sat there in the task, next to the estimate, being much larger than the estimate implied.
Where it was going. Not into writing code. The largest single line item was reconnaissance: the executor was assembling its own context — hunting for types, for file paths, for signatures, reading neighbouring packages to work out how things were done around here. After reconnaissance came repeat runs, and after that, rework.
What that actually meant. The same fact — one type name, one signature, one convention — was being rediscovered independently by every executor that touched that area. The cost of a fact was being multiplied by the number of people who needed it, and nobody was writing the fact down anywhere it would be found next time.
What changed. The spec grew two things: a closed list of files for each iteration, and a section called facts of the set. A fact is written once, in the spec. Reading is limited to the named files — at most three of them. Searching the tree is not permitted.
What is visible today. As of 2026-08-16: 298 spec files, more than 20 closed sets, 3 sets in flight, 5 written but not yet taken, and the largest single set at 41 files. Real set sizes, for scale: 13, 12 and 40 iterations.
I am not going to attach hours or money to that case. Those values do not exist in my records, and putting invented ones next to a real argument is how a real argument stops being trusted.
The part worth keeping is this: the 350 000 was only ever visible because the task carried an estimate and a recorded fact. Without both, it is an executor that finished its work. With both, it is a spec defect with a price on it.
How this is normally done
Nothing below is a criticism; it is the baseline I diverged from, and it is a reasonable baseline.
| Practice | The common shape |
|---|---|
| Estimate | Abstract units of complexity — story points, deliberately not hours, deliberately relative |
| Status | Movement through a board, largely as reporting upward to a manager |
| Reflection | A retrospective at the end of an iteration, discussing the period as a whole |
| Incidents | Written up afterwards, in a postmortem, for the events big enough to warrant one |
The reason points avoid hours is sound: hours invite the estimate to be read as a commitment, and relative sizing between people is more stable than absolute sizing. The reason retrospectives are periodic is also sound — a period gives you a sample.
My problem with the baseline is narrower than "it's wrong". It is that none of those four practices attaches a number to one requirement. They attach numbers to a period, a board, or an outage.
What I do instead — four practices, on every task
1. An estimate is mandatory
Every task carries an estimate before work starts. The scale is hours of executor time: 1 point ≈ 1 hour of an executor's run.
| Property | Rule |
|---|---|
| When | Set before the work starts, never after |
| Scale | Hours of executor time, not abstract complexity |
| On scope change | Revised explicitly, as a visible edit, not quietly absorbed |
| What it excludes | Human hours. This estimates the run, not the labour |
That last row is the one people push back on, and the pushback is fair — it is the exact thing story points were invented to avoid. My defence is that this scale is not measuring a person, so it cannot be used as a promise extracted from one. It measures a run whose actual cost is recorded afterwards in the same units. An estimate you can compare against a fact in the same unit is worth more to me than an estimate that is safe from misuse.
2. Status moves on every transition
taken into work ────► PR opened ────► accepted
│
└──► blocked on something external
(a status, not silence)
Three transitions, each one moved the moment it happens. The fourth state matters most: when a task is waiting on something outside it, that is a named status, not a task that has gone quiet. Silence and blocked look identical from outside and cost very different things.
3. Incidents are recorded at the moment they happen
Five categories. One line each, written when the thing occurs.
| Category | What it catches |
|---|---|
| Executor error | The work was done wrong against a spec that was clear |
| Scope change | The requirement moved after the task was estimated |
| Spec ambiguity | The spec permitted two readings and the wrong one was taken |
| Technical surprise | Reality differed from what the spec assumed |
| External block | Progress stopped on something outside this task |
And one rule that does more work than the five categories combined: reconstructing incidents after the fact is itself an incident. Not a scolding — a data-quality statement. Numbers assembled from memory at the end of a task are numbers you cannot act on, so the act of assembling them late gets recorded as the defect it is.
4. A final report closes the task
Every task ends with a report in a fixed shape, so that tasks are comparable to each other:
time executor · human · pauses
tokens ─
money ─
external calls ─
incidents ─
estimate ─
actual ─
result ─
The slots above are empty on purpose. I am publishing the shape of the report, not a filled example — I do not have a sanitised filled one to show, and inventing plausible hours and dollars to make a figure look complete would undo the entire point of the section.
What the thread makes visible
Every number below exists only because each task carries an estimate and a recorded fact. Remove either one and these are anecdotes.
| What | Value |
|---|---|
| Tokens per iteration, one early set | ≈ 350 000 |
| Largest expense inside that | Reconnaissance — types, paths, signatures, neighbouring packages |
| Real set sizes | 13 · 12 · 40 iterations |
| Spec files, as of 2026-08-16 | 298 |
| Closed sets | 20+ |
| Sets in flight | 3 |
| Written, not yet taken | 5 |
| Largest single set | 41 files |
The distribution is the interesting part. Sets of 13 and 12 iterations sit next to a set of 40, and knowing which shape you are about to start is the difference between an estimate and a guess. That distribution is only knowable because the closed sets kept their numbers.
Signals that a task was expensive
Five of them. Each is one line in the task, and any one of them means the work cost more than the estimate implied:
- A clarifying question had to be asked.
- A rule fired and blocked something.
- Two iterations edited the same file.
- An iteration was rewritten after acceptance.
- An iteration consumed more context than its named files could account for.
All five are read the same way, and this is the part that decides whether the practice survives contact with people: these calibrate the spec, not the executor. A clarifying question means a sentence was ambiguous. A rewrite after acceptance means the readiness criterion was wrong. The moment any of these is read as a performance signal about whoever did the work, recording them honestly stops, and the whole thread turns into fiction that costs time to produce.
Why this shape
Because the estimate and the fact are in the same unit. Hours of executor time, estimated up front, hours of executor time recorded afterwards. That gives one number you can put next to the value of the requirement and ask whether the trade was worth making. Two numbers in different units — points against dollars, complexity against duration — cannot be compared without a conversion nobody agrees on.
Because incident categories answer "what do I fix", not "who was wrong". Each category has a different repair, and the repair is what makes the category worth writing down:
| Category | What it repairs |
|---|---|
| Spec ambiguity | Fixed in text — the sentence gets rewritten |
| Executor error | Fixed by an external check, not by asking for more care |
| Scope change | Fixed in the estimate, explicitly and visibly |
| Technical surprise | Fixed in the facts section, so the next set inherits it |
| External block | Fixed by making the wait visible, not by waiting quietly |
Two of those repairs are the subject of the next parts of this series. Ambiguity is repaired by making the spec exhaustive. Executor error is repaired by a check that runs whether or not anyone remembers to run it.
The multiplier
An automated executor makes the accounting cheap — the numbers can be pulled and folded into a report without anyone typing them. What it does not do is decide what counts as an incident, or what the estimate should have been, or which of the five categories a given failure belongs in. Those are judgements, and the whole value of the thread is in them. Cheap measurement amplifies whoever set the definitions; it does not supply the definitions.
What this costs
- It taxes every task. Estimating, moving status, writing incidents as they happen and closing with a report all take time on every single task, including the tiny ones.
- It is the first thing to be dropped under pressure. When a deadline is close, the accounting is what gets skipped, and it gets skipped exactly when the data would have been most useful.
- Late reconstruction produces numbers you cannot trust. Which is why it is classified as an incident rather than as a catch-up — the alternative is a tracker full of confident, wrong figures.
- The scale does not transfer. "One point ≈ one hour of an executor run" is not a scale for estimating a team of people, and using it that way would reproduce every problem story points were designed to solve.
When not to do this
- A one-off change. Seven fields of accounting around a single-line fix is ceremony, and I skip it.
- A task with no readiness criterion. If there is nothing to accept, there is no end to the thread, and a report on an unaccepted task is a report on nothing.
- Somebody else's process. Where status already carries a different meaning — a contractual milestone, a billing state — overloading it with a second meaning breaks the first one.
The honest caveat
The estimates, the incidents and the budgets described here are kept on my own tasks. There is no multi-person sample behind any of it, and I would be misrepresenting it if I presented these numbers as an industry finding rather than as one practitioner's log.
There is also no separate analysis function in this setup: requirements are formulated by the person who owns the task. That works at this size and it is a known limit, not a design principle.
From requirement to contract — Part 3. Next: watching a process is not the same as gating it — where the checks sit on the transitions themselves, so that a step cannot be passed rather than merely being observed.
If you do this better, tell me what unit your estimate and your actual are both recorded in. If you have been through this, what did your version of the 350 000 turn out to be hiding? If you see it differently, say where per-task accounting cost you more than it returned. How is it solved on your side, and what broke there?





Top comments (0)