Writing a ticket
The ticket is the whole input. Everything Styre does downstream is derived from it, and nothing later can go back and ask you what you meant — so this is the page worth reading twice.
What Styre actually reads
Section titled “What Styre actually reads”You control exactly three things: the title, the description, and one label.
- The title is the only text every stage sees. Write it as a standalone claim, not a label. “Retry the checks fetch on 5xx” beats “Checks bug”.
- The description is read once, by the design stage. Everything after that works from the plan design produced, not from your words.
- The label —
Bug,FeatureorImprovement— decides your branch prefix and nothing else.
The template
Section titled “The template”## What
One to three sentences, in the imperative. Name the files and symbols youactually know. If you know the offending code, quote it with a file:line ref.
## Why
The evidence. A failing command, a log line, a measured number, a link. If youassert a defect, prove it here. Also name the obvious alternative fixes youalready ruled out and why — otherwise design will re-derive them.
## Scope
**IN**
* Bullets, not checkboxes — see the warning below.* Only as precise as your evidence supports.
**OUT**
* What this ticket deliberately does not do, and why.* Name the sibling ticket that owns the excluded work, if there is one.
## Acceptance criteria
- [ ] Self-contained, observable, specific. Each line becomes one test.- [ ] Your project's gate — build, tests and lint all pass.
## Refs
* Sibling tickets, design docs, links to the evidence.Acceptance criteria decide the outcome
Section titled “Acceptance criteria decide the outcome”This is the part that matters most. Each checklist item becomes one test, written before the work starts, that must fail on today’s code and pass when the work is done.
Four rules.
1. Always write a checklist
Section titled “1. Always write a checklist”If your description contains no checkboxes at all, the entire description is treated as a single coarse criterion. One vague test then stands in for the whole ticket. It is the worst result available to you, and it is the default if you forget.
2. Each criterion must stand on its own
Section titled “2. Each criterion must stand on its own”The step that writes your tests sees the criterion text and nothing else — not your What, not your Why, not the other criteria. Anything that depends on context elsewhere in the ticket is unverifiable.
| Instead of | Write |
|---|---|
Handle the error case. |
parseFoo("") returns an empty array rather than throwing. |
The message explains the problem. |
When the file was deleted, the message says it was created and since removed, and tells the agent not to search for it. |
Retries work. |
A 503 from the checks API is retried three times with backoff before the run gives up. |
A good test: cover up the rest of the ticket. Can someone still write the test?
3. Name an observable output, with a specific value
Section titled “3. Name an observable output, with a specific value”returns 200 is not a criterion — a stub that returns 200 {} satisfies it without doing any of
the work. Say what the response contains. For anything numeric or algorithmic, state the actual
value the fixed code must produce, not a property that would hold either way.
4. It must be false today
Section titled “4. It must be false today”Every criterion needs to be something that fails on current code for the right reason. If it already passes, it is not testing your change.
End the checklist with your project’s real gate, whatever that is:
- [ ] `npm run build`, `npm test` and `npm run lint` all pass.Scope, and how much you need to know
Section titled “Scope, and how much you need to know”Always write Scope OUT. It is a decision, not a discovery — you can say “don’t touch the auth module” without knowing anything about the code. It costs nothing and it is your only defence against a change that sprawls.
Write Scope IN only as precisely as you have earned. If you have investigated, name files and quote lines. If you have not, describe the outcome you want and stop there.
Do not list the test files that prove your criteria, either. Styre names and writes those itself.
Two things that work differently than you would expect
Section titled “Two things that work differently than you would expect”A richer ticket does not buy a shorter pipeline. Design always runs at full strength, no matter how well-specified the ticket is. More detail improves the plan; it never skips a stage.
One ticket, one concern. Two unrelated problems in one description produce a plan that solves both halfway. Split them, and use Refs to keep the pieces connected.
Before you hand it over
Section titled “Before you hand it over”- The title is a standalone claim.
- Exactly one label:
Bug,FeatureorImprovement. - There is a real checklist under Acceptance criteria.
- There are no checkboxes anywhere else.
- Every criterion reads and verifies with the rest of the ticket covered up.
- Every criterion names an observable output and its expected value.
- No criterion would be satisfied by a trivial stub.
- Every criterion is false on today’s code.
- The last criterion is your project’s build, test and lint gate.
- Any file path you named, you have verified. Naming none is fine.
- Scope OUT is present.
- Why cites real evidence and rules out the obvious alternatives.
- One concern.
Next: The run loop — what Styre does with the ticket once you hand it over.