Skip to content

feat(ticket-polish): pick a body shape, write it in the house emoji grammar - #52

Merged
jtomaszewski merged 2 commits into
mainfrom
jt/ticket-polish-body-shape
Aug 28, 2026
Merged

feat(ticket-polish): pick a body shape, write it in the house emoji grammar#52
jtomaszewski merged 2 commits into
mainfrom
jt/ticket-polish-body-shape

Conversation

@jtomaszewski

@jtomaszewski jtomaszewski commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

The problem

ticket-polish §4 was a single sentence — "what this is → what's left → why the closed things are closed → evidence → DoD" — against pr-polish §4's six specified sections, readability test and three writing rules. Three consequences:

  • No slot for a problem statement. A polished ticket could open at "one task, two steps…", asking its reader to agree to a plan before meeting what's broken.
  • The budget rule blocked the fix. "Never pad, never add sections" is right for an accreted body and wrong for a thin one. The skill was written for bodies that have too much and had nothing to say about a body missing the two things that make a ticket judgeable.
  • No section grammar at all, so two polished tickets looked nothing alike and neither looked like our PR bodies.

Same gap on the DoD: ticket-refresh assumes 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?

No  → originating   🎯 problem · 🔧 what we do about it · 🔍 detail · ⚠️ risk · ✅ Done when
Yes → hub           link · 📋 owned here · ✅ Steps · ❓ open questions · ⚠️ constraints · 📜 landed

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 when or ✅ 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 success is most of what anyone reads on a collapsed tracker view; ## The problem is 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.yml marks Problem Statement required: true and Solution Brainstorm required: 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-only task.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.

version bumped 1.5.01.6.0 (new capability in an existing skill, per AGENTS.md) and the README row updated.

🤖 Generated with Claude Code

§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.
@jtomaszewski jtomaszewski changed the title feat(ticket-polish): pick a body shape, and add a missing problem or DoD feat(ticket-polish): pick a body shape, write it in the house emoji grammar Aug 27, 2026
@jtomaszewski
jtomaszewski merged commit e984a8c into main Aug 28, 2026
1 check passed
@jtomaszewski
jtomaszewski deleted the jt/ticket-polish-body-shape branch August 28, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant