Write an issue
These rules govern the opening post of an issue only. The opening post is where every reader's attention lands first, so it is held to a fixed structure. Any material — investigation notes, log excerpts, dead ends, corrections — may appear in the opening post when it fits the structure below. Comments have no guidelines at all.
Write for a reader who knows the product but did not do the investigation.
Explain before you name; count concepts, not words. The explain-properly
skill's guidelines on density apply to every section below.
Structure
Three sections are mandatory and come first, in this order. Two more depend on whether the root cause is known. Three optional ones may follow.
- Summary
- Severity
- Occurrence
- Technical context and root cause — only when the cause is identified
- Suggested solutions — only when section 4 exists
- Optional: Detection, Workaround, Acceptance
A reader who stops after section 3 must have a complete picture of what the problem is, how bad it is and who gets it. Sections 4 and 5 are for the person who will fix it.
1. Summary
Two to four sentences. It must state:
The kind of issue: bug, performance problem, feature request, hardening with no observed failure, etc.
The domain: whether the issue is about user-facing behaviour of Spindle, or about internal infrastructure, or something else — and which named area, using the names below so that two areas that sound alike are never confused. The list grows as further areas are identified.
User-facing, shipped to users inside
spindle-client:- the Claude Code plugin — the hooks, skills and MCP tools that run inside a user's Claude Code session (extraction, injection, rating)
- the client CLI —
spindle-clientcommands the user runs by hand - the client daemon — the background process that uploads sessions
- the client review UI — the local web page the daemon serves, where a user reviews their own requirements
- historisation — the git-side attribution of messages to files
Internal, run by the team:
- the Dev UI — the server-side web UI at ui.dev.codespeak.dev that developers use to browse uploaded sessions, requirements and feedback. Not the client review UI: a bug here reaches developers, not users
- the server — the upload and admin plane
- the worker — the Temporal workloads (parse, annotate, replay)
- the object store — the shared storage library every side writes through
- repository tooling — CI, mise tasks, lint, release
The context needed to follow sections 1 to 3 — and nothing more. For example, if the defect is in retrieval, one sentence explaining what retrieval is and why we need it lands here. The goal is not to teach a person who genuinely does not know, but to fill the small yet crucial gaps of a knowledgeable reader and, importantly, to prevent term mismatches. In our example, the reader might not have the term "retrieval" in mind; a brief explanation that it is the selection of requirements relevant to the user's prompt, used as input for extraction, clears up any misunderstanding.
Litmus test: every term used in sections 2 and 3 is either common knowledge for the team or introduced here.
2. Severity
What happens when the issue manifests. Nothing about how it manifests or how rare it is — that is section 3.
The first sentence is the judgement, on its own: how bad it is when it happens, in one sentence a skimming reader can take away without reading on. "A session silently loses requirement extraction for the rest of its life." "A count in a log line is off by one." The rest of the section expands on that sentence:
- the expected behaviour;
- the actual behaviour;
- how blocking it is for the affected party: silent data loss, a visible error they can work past, a dead session, a wasted resource, a cosmetic flaw;
- whether the effect is contained to the triggering party or spreads to others.
Write this as if the issue manifests every time. The most obscure race and the most common misclick get the same treatment here.
State the effect on a person: what a user sees, loses or has to do by hand, or what the developer team can no longer do. Two things are not effects, however true they are:
- an abstract noun — "the requirement has no provenance";
- a property of the system — "the message link leads nowhere".
Both describe the state of the system, not what it costs anyone. The test is a scenario: a named kind of person, doing a named thing, and what goes wrong for them. "A developer reviewing extraction quality opens the session in the Dev UI and the requirement is missing beside the prompt that produced it" is an effect. If you cannot write such a scenario, you have not found the effect yet — keep looking, or say plainly that no effect on anyone is known.
3. Occurrence
Who gets the issue and how often. Nothing about how bad it is — that was section 2.
The first sentence is the predicate: the condition under which the issue arises, stated as a fact about the world. "Anyone who runs Claude Code through remote control." "Any session whose transcript is too large to materialize inside the stop hook's budget, on a machine with other sessions writing the same store." A predicate is a fact and stays true; how common the situation is is a judgement, and later passes over the issue may revise it. So the predicate leads and the estimate follows. The rest of the section expands on it:
- the conditions in full, as facts about the world (transcript size, number of concurrent sessions, a flag, a version), not as code paths;
- the reproduction, when there is a recipe;
- the estimate: how many consumers the predicate covers and how often it holds. This is reasoning more often than measurement, and reasoning is fine; say which it is. Where a number exists, give it, and say what it was measured on;
- whether it has been observed at all. A hazard found by reading the code is a legitimate issue, but the reader must know it is a reading, not an observation.
4. Technical context and root cause
Only when the root cause is identified. Technical context without a root cause is guesswork dressed as analysis and misleads the next investigator, so the opening post carries none.
Introduce the mechanism in the order the reader needs it: what the component is for, then how it does it, then what exactly is wrong. Quote code only where the explanation turns on the exact line. Every quoted symbol is one more term the reader has to carry.
When more than one defect contributes, number them and say which is the root and which are consequences or amplifiers. Say explicitly what is not the problem when a reader would otherwise suspect it.
5. Suggested solutions
Only when section 4 exists: a fix without a root cause is a guess. This section proposes changes to Spindle. What an affected party can do today, without any change, is not a solution and goes to the optional Workaround section, which needs no root cause.
Number the options. Where several defects were listed in section 4, say which fix addresses which, and give an order when it matters. Name what is deliberately out of scope.
Optional sections
- Detection: how the problem was found, and whether it would be noticed next time. Belongs here when the answer is "by accident" or "it would not".
- Workaround: what an affected party can do today, without a fix.
- Acceptance: what proves the fix — typically the regression test that must fail before the fix and pass after it.
Title
The title states the defect and its consequence, not the mechanism: "A revert deletes a requirement instead of demoting it" rather than "presentSet derives from tombstone links". A reader scanning the issue list should be able to rank it without opening it.
Review with the reporter
Before the issue is posted, show the user who asked for it three things, in your reply and verbatim from the draft:
- the Summary;
- the Severity judgement — the first sentence of section 2;
- the Occurrence predicate — the first sentence of section 3.
These are the parts that drive every later decision about the issue — whether it is worked on, when, and by whom — and they are also the parts most likely to be wrong, because they are judgements rather than findings. The reporter must be able to correct them without reading the whole draft. Do not bury them in a link to the file or a "see the draft"; print them.
Before posting
- Sections 1 to 3 stand alone: a reader who stops there knows what, how bad, and who.
- Section 2 opens with the severity judgement; section 3 opens with the occurrence predicate. Each is one sentence and the rest of its section expands on it.
- Severity says nothing about frequency; Occurrence says nothing about damage.
- Occurrence distinguishes fact from estimate, and observation from reading.
- No section 4 without a root cause; no section 5 without section 4.
- Every term is introduced before it is used, and the same thing is called the same name throughout.
- Code is in fenced blocks; prose names at most one symbol per sentence.
- Environment facts — client version, session, machine — are present and exact.
- The Summary, the severity judgement and the occurrence predicate have been shown to the reporter.