feat(ticket-polish): pick a body shape, write it in the house emoji grammar - #52
Merged
Conversation
§4 was one sentence ("what this is → what's left → …") with no slot for a
problem statement and no writing rules, while §4 of pr-polish specifies six
sections and three rules. The budget line then said "never pad, never add
sections", so the skill actively blocked supplying what was missing: it was
written for bodies that have too much, and does nothing for one that opens
mid-plan with no statement of what is broken.
§4 now picks between two shapes on one test — does a live artifact elsewhere
already state the problem? — and carries two invariants regardless: the problem
is stated somewhere reachable, and exactly one checkable DoD exists. Both
shapes ship as skeletons under templates/.
Shapes follow public practice rather than taste. Where the ticket is the only
record, problem-first with an optional solution is near-universal: Sentry's
feature.yml marks Problem Statement required and Solution Brainstorm optional;
Shape Up's pitch opens with Problem ("It's critical to always present both a
problem and a solution together"); GitLab's feature proposals open with
"Problem to solve"; Kubernetes' enhancement form requires "Why is this needed?".
Where the problem lives upstream, bodies are hubs with no problem statement at
all: Rust's tracking issue is a link to the RFC plus Steps, Unresolved
Questions and Implementation history.
The counter-pressure is real and shaped the budget rule: Linear's method says
descriptions "should be optional–not required", and maintainers surveyed in an
empirical study of 350 templates across 100 projects warn that templates
"accrue a lot of cruft, be overly specific/rigid" and are "mostly challenging
for existing contributors". So every section outside the two invariants is
optional and gets deleted, and headers stay banned until a body needs them.
Also §3: a new decay shape for a body that opens mid-plan, "stale DoD" widened
to "missing or stale". §6 reports the shape when it changed, since hub →
originating means an upstream artifact stopped carrying the problem.
Both skeletons now carry the fixed-emoji, free-heading grammar the house already uses for PR summaries, so a reader crossing from a review to a PR to a ticket meets one alphabet: originating 🎯 problem · 🔧 what we do · 🔍 detail ·⚠️ risk · ✅ Done when hub link · 📋 owned here · ✅ Steps · ❓ open ·⚠️ constraints · 📜 landed The load-bearing part is not the emoji, it is that the emoji and the order are fixed while the words after them are written for this ticket. On a collapsed tracker view "### 🎯 A failed backfill reads as success" is most of what anyone reads; "## The problem" is none of it. The plain label stays available for when nothing sharper fits. Three guards keep a fixed set from turning into a form: drop every section with nothing real under it, no headings at all below two paragraphs, and 🔍 may repeat in a long originating body rather than minting a history emoji — the hub has 📜 because tracking what landed is what a hub is for. Invariant 2 tightened while here: exactly one checkable DoD, and a single sentence qualifies. Trialled against three real tickets — a fresh bug, a three-week-old umbrella with two measurement tables, and a spec-tracking umbrella; the umbrella is what surfaced the repeated-🔍 case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
ticket-polish§4 was a single sentence — "what this is → what's left → why the closed things are closed → evidence → DoD" — againstpr-polish§4's six specified sections, readability test and three writing rules. Three consequences:Same gap on the DoD:
ticket-refreshassumes a "Done when" exists,ticket-polish§3 defines what a good one looks like, and nothing told §4 to create one.The change
§4 now picks a shape on one test — is there a live artifact elsewhere (spec, RFC, design doc, brief, parent ticket) that already states the problem?
Both ship as skeletons in
templates/. Two invariants hold in either shape: the problem is stated somewhere reachable, and exactly one checkable DoD exists (✅ Done whenor✅ Steps, never both — a single sentence qualifies).A ticket changes shape when its upstream artifact is retired or absorbed — which is the usual reason a body opens mid-plan, so §3 gets that as a named decay shape and §6 reports a shape change, since it's a fact about the project and not about the prose.
The grammar, and why the emoji aren't the point
The emoji and the order are fixed; the words after them are written for this ticket.
### 🎯 A failed backfill reads as successis most of what anyone reads on a collapsed tracker view;## The problemis none of it. The plain label stays available for when nothing sharper fits.This is lifted from the summary format the house already uses for PR reviews, so one alphabet spans review → PR → ticket. Three guards stop a fixed set from becoming a form: drop every section with nothing real under it, no headings at all below two paragraphs, and
🔍may repeat in a long originating body rather than minting a history emoji — the hub carries📜because tracking what landed is what a hub is for.Why these shapes
Not taste — this follows what's actually in other people's templates.
Ticket is the only record → problem required, solution optional. Sentry's
feature.ymlmarksProblem Statementrequired: trueandSolution Brainstormrequired: false. Shape Up's pitch opens with Problem: "It's critical to always present both a problem and a solution together." GitLab's feature proposals open with### Problem to solve. Kubernetes' enhancement form requires both "What would you like to be added?" and "Why is this needed?". Home Assistant's staff-onlytask.yml— the closest public analogue to an internal work item — asks for what needs doing, why it's needed, and the expected outcome.Problem lives upstream → hub, deliberately without one. Rust's tracking issue is one line linking the RFC, then
Steps,Unresolved Questions,Implementation history. Kubernetes says it outright in the form: "Feature requests are unlikely to make progress as issues… can be opened as a KEP."Ticket read by an agent → acceptance criteria stop being optional. GitHub's coding-agent docs: an ideal task has "A clear description of the problem to be solved or the work required. Complete acceptance criteria on what a good solution looks like", and "think of the issue you assign… as a prompt".
The strongest argument against, and what it changed
Adding structure to a skill whose job is subtraction is how template cruft starts. Linear's method: descriptions "should be optional–not required". Maintainers surveyed across 350 templates in 100 projects warn that templates "accrue a lot of cruft, be overly specific/rigid" and are "mostly challenging for existing contributors who know when they're already providing enough information" — which is exactly this skill's user. GitLab, meanwhile, is running 97 issue templates in one repo.
So the budget rule survives with a narrow exception rather than being replaced: everything outside the two invariants is optional and gets deleted, headings stay banned until a body needs them, and a three-line ticket stays three lines.
Verification
Doc-only change to one skill. Trialled by hand against three real tickets before landing — a fresh bug report, a three-week-old umbrella carrying two measurement tables and four blocks of work, and a spec-tracking umbrella. The bug came out unchanged in substance, which is the point: a ticket that is already good should not pay a template tax. The big umbrella is what surfaced the repeated-
🔍case, and the spec-tracking one is what confirmed the hub shape drops a duplicated Definition-of-Done list.versionbumped1.5.0→1.6.0(new capability in an existing skill, per AGENTS.md) and the README row updated.🤖 Generated with Claude Code