19db0a933a
Rule 4 ("Self-contained") forbade dangling pointers by example only, so
a reference reachable only through the producing chat slipped past it --
e.g. a shipped comment "Approach B (the mechanism refinement decided +
logged above)", whose "logged above" names no resolvable entry and whose
"Approach B" indexes an A/B fork the entry never reproduces.
Reframe rule 4 around one test: a reference is valid iff a reader who
lands on the entry alone (e.g. via a direct comment-anchor link) can
follow it to its target. A survey of the live tracker (63 issues / 96
comments) found 56 violations in six classes, now each named as an
unreachable form: chat references, weak intra-thread pointers
("above" / "logged above"), artifacts named by role, out-of-repo paths,
bare un-glossed codes, and locator-shaped tokens that resolve to nothing.
Carve-outs keep inline quotations, #N / SHA / URL / repo-path locators,
glossed codes, and restated forks legitimate. The constructive escape
hatch (log a chat decision to the tracker first, then cite that comment)
cross-references boss "The reference issue".
Align the Common-mistakes table, the Red-flags STOP gate, and the boss
cross-reference. Prescribe a comment's full URL rather than a bare
#issuecomment-NNNN fragment, which is not auto-linked on Gitea and so
does not itself satisfy the test.
Existing tracker entries are left unedited; the rule governs future
writing only.
229 lines
12 KiB
Markdown
229 lines
12 KiB
Markdown
---
|
|
name: issue
|
|
description: Use when creating, editing, commenting on, or closing a Gitea issue — filing a bug, feature, or idea into the tracker, or turning a finding into a tracker item. Covers the issue-writing conventions and the tea-CLI mechanics for the operation.
|
|
---
|
|
|
|
# issue — write and edit Gitea issues
|
|
|
|
> **Violating the letter of these rules is violating the spirit.**
|
|
|
|
## Overview
|
|
|
|
An issue is a durable artefact in the forward-queue, read later by
|
|
humans and by other agents — usually without the conversation that
|
|
produced it. It must stand on its own. This skill unifies how issue
|
|
text is written so every issue reads the same way, and records the
|
|
`tea` mechanics for creating and editing them.
|
|
|
|
An issue states facts and clearly-flagged claims about a concern. It
|
|
is not a chat message.
|
|
|
|
## When to use
|
|
|
|
| Situation | Use this? |
|
|
|---|---|
|
|
| "Open an issue for X" / "file a bug about Y" | Yes |
|
|
| "Edit / re-label / comment on issue #N" | Yes |
|
|
| "Close #N" (outside a `closes #N` commit) | Yes |
|
|
| Turning a finding or deferred work into a tracker item | Yes |
|
|
| A note relevant only to the current conversation | No |
|
|
|
|
Other skills file issues through these same conventions — e.g.
|
|
`brainstorm` parks a deferred spec as a backlog issue, `audit` files
|
|
regressions, and `boss` files skill-system deficiencies against the
|
|
plugin's own tracker (with an autonomous-provenance body block — see
|
|
`../boss/SKILL.md` § Skill-system feedback). This skill is the shared
|
|
convention they lean on.
|
|
|
|
## The four writing rules
|
|
|
|
These apply to every issue, on create and on edit.
|
|
|
|
1. **No direct address.** Impersonal, declarative voice. No "you",
|
|
no imperative aimed at the reader. State the situation, not
|
|
instructions to a person.
|
|
- Avoid: "You need to fix the parser because you broke escaping."
|
|
- Use: "The parser drops backslash escapes in quoted strings."
|
|
|
|
2. **Validated or flagged.** Every factual statement is either
|
|
verified — carrying its evidence (command output, log line,
|
|
`file:line`, a reproduction) — or explicitly marked as an
|
|
unverified claim, so a reader never mistakes a guess for a fact.
|
|
- Verified: "`parse()` returns `None` for `a\"b` — see
|
|
`parser.rs:84` and the repro below."
|
|
- Flagged: "Claim (unverified): the regression likely landed in
|
|
0b96983; not yet bisected."
|
|
- Where it sharpens the point, drop in a concrete code example —
|
|
the snippet that triggers the failure, or the call as it
|
|
*should* behave. A fenced block beats a prose paraphrase:
|
|
|
|
````
|
|
```rust
|
|
parse("a\"b") // => None, want Some("a\"b")
|
|
```
|
|
````
|
|
|
|
3. **Imperative, concise title.** Verb-first, one line, no trailing
|
|
period — scannable in the list, mirroring commit-message style.
|
|
Checkboxes (`- [ ]`) are allowed in the body for sub-points or a
|
|
small acceptance checklist.
|
|
- Avoid: "parser bug" / "There is a problem with the parser."
|
|
- Use: "Preserve backslash escapes in quoted strings"
|
|
|
|
4. **Self-contained — the reachability test.** The issue stands on its
|
|
own, without the conversation that produced it. Apply one test to
|
|
every reference: *starting from this entry alone — a reader may have
|
|
arrived by a direct comment-anchor link, no chat and no sibling
|
|
comments loaded — can they follow it to its target?* If not, it is a
|
|
dangling pointer: reproduce the content inline, or swap in a
|
|
resolvable locator.
|
|
|
|
**Reachable — use these:** content stated or quoted inline; an
|
|
issue/PR number (`#42`, or cross-repo `Skills #11`); a commit SHA
|
|
(`a1b2c3d`, resolves on push); a full URL; a repo-relative path,
|
|
optionally with a line range (`parser.rs:84-90`); another comment by
|
|
its full URL (the link ending `#issuecomment-NNNN` — the bare fragment
|
|
only resolves in-page on that comment's own issue); a same-entry
|
|
section marker (`§5`); a convention-resolvable in-repo slug (a
|
|
`docs/specs/` slug, a cycle number).
|
|
|
|
**Unreachable — rewrite or inline; these never resolve from the
|
|
tracker:**
|
|
- **The producing chat by reference, in any phrasing** — "the
|
|
in-context discussion", "settled before the run", "the session /
|
|
cycle transcript", an in-context juror/panel verdict (`D3`). No
|
|
anchor can ever reach it; the irrecoverable case. (Quoting the
|
|
decision's words inline is fine — see the carve-out below.)
|
|
- **A weak prose pointer** — "above", "below", "earlier", "the prior
|
|
comment", "logged above", "as discussed" — with no resolvable
|
|
locator: the target comment's full URL, a `#N`, or a *same-entry*
|
|
`§` marker. A `§` pointing into another comment or file is itself
|
|
unreachable — link that comment's URL.
|
|
- **An artifact named by role, not locator** — "the OOS harness
|
|
issue", "see the ledger", a `Depends on` target — carrying no `#N` /
|
|
SHA / URL / repo path.
|
|
- **A path outside this repo** — `/mnt/...`, `~/.claude/...`, a Claude
|
|
auto-memory slug, another project's `BLOCKED.md`. Only a path in
|
|
*this* repo is reachable.
|
|
- **A bare code or ordinal whose defining set the entry does not
|
|
reproduce** — a plan-item / ledger / lens code (`I7`, `C16`), an
|
|
index ("decision #5"). Gloss it in place, or restate the set.
|
|
- **A locator-shaped token that resolves to nothing** — a template
|
|
placeholder (`#(A)`), or a `#`-number in the wrong format (`#0071` —
|
|
issue refs are unpadded integers like `#71`; a leading zero matches
|
|
nothing).
|
|
|
|
A chat decision becomes referenceable only by being **written to the
|
|
tracker first** — log it, then cite that comment; a chat is reachable
|
|
by being written down, never by being pointed at (the `boss`
|
|
reference-issue mechanic, `../boss/SKILL.md` § The reference issue).
|
|
|
|
**These stay self-contained** (don't strip them chasing the rule): an
|
|
inline dated verbatim quote of a chat decision ("`mach es so!` —
|
|
2026-06-29") — the reader sees the exact words, and only a surplus
|
|
"settled in-context" sentence *beside* it is the violation; an
|
|
enumerated fork `(A)`/`(B)` whose options are restated here; a
|
|
glossary code glossed inline; a provenance sentence whose fact is also
|
|
stated inline, so long as it embeds no unresolvable pointer (keep
|
|
"decided", drop or anchor "logged above"). Flag the *pointer* a
|
|
tracker-only reader can't resolve, never the content it reproduces.
|
|
|
|
- Avoid: "Approach B (the mechanism refinement decided + logged
|
|
above)." — "logged above" points to a sibling comment with no
|
|
resolvable URL, so a reader who landed on this comment can't reach
|
|
the refinement; the violation is the unresolvable pointer, and it
|
|
stands even when the mechanism is restated inline. The bare label
|
|
"Approach B" compounds it — it indexes an A/B fork this entry never
|
|
reproduces, so the letter means nothing to a reader who didn't see
|
|
the fork laid out.
|
|
- Use — drop the chat-native label, name the option on its own terms,
|
|
then inline or link the refinement: "The honest per-held-cycle bleed
|
|
(accrue each held cycle, dump at close) — refined in
|
|
`http://…/issues/148#issuecomment-2142`."
|
|
|
|
**Language:** title and body are English — an issue is a repo
|
|
artefact mirrored to Gitea ("would it be committed → English", per
|
|
`~/dev/CLAUDE.md`).
|
|
|
|
## tea mechanics
|
|
|
|
`tea` is pre-authenticated via its own config (`~/.config/tea/`).
|
|
Never read or echo that file — it holds a token. `tea` auto-detects
|
|
the repository from the git remote; override with `--repo owner/name`
|
|
when running outside the repo (the project's issue tracker — its
|
|
CLAUDE.md project facts name the repo slug and the list/show commands).
|
|
|
|
| Operation | Command |
|
|
|---|---|
|
|
| List open | `tea issues ls --state open` |
|
|
| View one | `tea issues <idx>` (body only) — add `--comments` to include the discussion thread: `tea issues --comments <idx>` |
|
|
| Create | `tea issues create -t "<title>" -d "<body>" -L "<labels>"` |
|
|
| Edit body/title | `tea issues edit <idx> -t "<title>" -d "<body>"` |
|
|
| Re-label | `tea issues edit <idx> --add-labels a --remove-labels b` |
|
|
| Comment | `tea comment <idx> "<body>"` |
|
|
| Close / reopen | `tea issues close <idx>` / `tea issues reopen <idx>` |
|
|
|
|
Notes:
|
|
- The body flag is `--description`/`-d`, **not** `--body`. For a
|
|
multi-line body pass a heredoc via command substitution:
|
|
`tea issues create -t "..." -d "$(cat <<'EOF'` … `EOF`\n`)"`.
|
|
- Labels are matched by name (`-L feature,bug`); they must already
|
|
exist in the repo. The project's label vocabulary lives in
|
|
`~/dev/CLAUDE.md` (`BLOCKER`, `feature`, `bug`, `idea`,
|
|
`in-progress`).
|
|
- Before editing, view the issue first (`tea issues <idx>`) — do not
|
|
edit blind. Status/discussion updates go in a `tea comment`, not by
|
|
overwriting the body. Note `tea issues <idx>` prints the **body
|
|
only**; pass `--comments` to read the existing thread first (the bare
|
|
form would otherwise prompt for it interactively, which hangs a
|
|
non-interactive agent).
|
|
- Routine closing is done by a `closes #N` line in the commit body on
|
|
push (per `~/dev/CLAUDE.md`); `tea issues close` is for closing
|
|
without an accompanying commit.
|
|
|
|
## Common mistakes
|
|
|
|
| Mistake | Why it's bad | Instead |
|
|
|---|---|---|
|
|
| "You should…" / reader-directed imperative | Breaks rule 1, ages badly | State the situation declaratively |
|
|
| A guess written as fact | Misleads future actors | Flag it: "Claim (unverified): …" |
|
|
| Title as a noun blob ("parser bug") | Not scannable | Imperative verb phrase |
|
|
| `-d` body with a guessed flag (`--body`) | tea rejects it | `--description`/`-d` |
|
|
| Editing without viewing first | Clobbers others' edits | `tea issues <idx>`, then edit |
|
|
| Reading/echoing tea's config | Token leak | tea is already authenticated |
|
|
| Pointer to the chat that produced the entry ("in-context", "the cycle transcript", a juror code) | The chat is invisible to a tracker reader — never reachable | Quote the words inline, or log the decision to the tracker and cite that comment's full URL |
|
|
| "above" / "below" / "the prior comment" with no anchor | A reader on a direct comment link can't tell which entry | Add the comment's full URL, a `#N`, or a *same-entry* `§` marker |
|
|
| Artifact or path named without a locator — "the harness issue", "see the ledger", `/mnt/...`, `~/.claude/...` | Nothing to navigate to from the tracker | Supply a `#N`, SHA, URL, or in-repo path — or reproduce the fact inline |
|
|
| Bare un-glossed code or ordinal (`I7`, `C16`, "decision #5") | Its defining set isn't in the entry | Gloss it inline, or restate the set |
|
|
|
|
## Red flags — STOP
|
|
|
|
- The word "you" anywhere in title or body
|
|
- A factual statement with neither evidence nor a "claim" flag
|
|
- A title that is a noun phrase or ends with a period
|
|
- A reference with no resolvable locator (`#N`, a commit SHA, a URL, an
|
|
existing repo path, a `docs/specs/` slug or cycle number, a same-entry
|
|
`§`, or the fact reproduced inline), or a bare never-glossed code whose
|
|
defining set isn't in the entry — in particular:
|
|
- a pointer to the chat that produced the entry ("in-context", "the
|
|
cycle transcript", a juror code); the chat is never tracker-reachable
|
|
- "above" / "below" / "the prior comment" / "as discussed" with no
|
|
resolvable locator — the comment's full URL, a `#N`, or a same-entry `§`
|
|
- an out-of-repo path (`/mnt`, `~/.claude`, a `memory <slug>`,
|
|
another project's `.md`) cited as the basis
|
|
- a `#`-token that resolves to nothing — a `#(A)` placeholder or a
|
|
wrong-format `#0071`
|
|
- About to `tea issues edit` without having viewed the issue
|
|
- About to print or `cat` the tea config
|
|
|
|
## Cross-references
|
|
|
|
- `~/dev/CLAUDE.md` — repo-English rule, label vocabulary, the
|
|
`closes #N` commit convention (the tracker is the forward-queue).
|
|
- `../brainstorm/SKILL.md`, `../audit/SKILL.md`, `../boss/SKILL.md` —
|
|
callers that file issues through these conventions. `boss` files
|
|
skill-system feedback with an autonomous-provenance body block
|
|
(§ Skill-system feedback), and its § The reference issue is the
|
|
constructive escape hatch for rule 4: log a chat decision to the
|
|
tracker first, then cite that comment instead of pointing at the chat.
|