When creating or editing a ticket, structure the description exactly as below. Fixed heading names — do not rename, reorder, or invent sections.
Three hard rules
- NO PII or PHI in tickets — ever. No patient/client names, emails, phone numbers, health card numbers, diagnoses, session content, or anything identifying a person. Refer to people by role + opaque ID (e.g. "client user_id 12345", "appointment 977096", support ref "ATS-13371"). Redact identifying details from screenshots, logs, and stack traces before attaching. This applies to every section, including Engineering Notes and comments.
- Acceptance criteria MUST live in the description body under a
## Acceptance criteriaheading, as a checklist. Write the description as ADF (contentFormat: "adf") and render the criteria as a real, tickabletaskList— see "Jira specifics" for the how. NEVER put them only in Jira's side-panel "Acceptance criteria" checklist field — QA, exports, PR links, and AI tools miss it there. ## Context,## Scope,## Acceptance criteria, and## How to test(when present) MUST use plain, human-friendly language that non-technical readers (QA, PM, support) can understand. Anything that only makes sense to developers — code paths, class/function names, SQL, stack traces, architecture detail — belongs under## Engineering Notes, below the---divider.
Template: Task / Story
## Context
Why this exists, 2–4 lines, in plain language. If there is a real end user, open with:
"As a <user>, I want <goal> so that <value>." Otherwise plain prose — never force a user story.
## Scope
What's in. What's explicitly out. Described as user/system behavior, not implementation.
## Acceptance criteria
* Testable, QA-facing statements written as observable behavior
* Include env / feature-flag prerequisites QA needs
## How to test
(Optional — include ONLY when the user explicitly asks for it. When present, follow
"How to test — writing guidance": numbered steps naming the exact app + URL, dev-tools
Network steps, the exact request/host, and the response field + expected values.
Omit by default.)
---
## Engineering Notes
(Optional, ALWAYS last, after the --- divider.)
Root cause analysis, code paths, PR/branch links, implementation ideas,
migration/rollback steps, log/NewRelic links. Nothing QA needs may live here.
Template: Bug
## Steps to reproduce
1. ...
## Expected
What should happen.
## Actual
What happens instead (screenshots / errors).
## Environment
* Env:
* Browser / client:
* Account / feature flags:
## Acceptance criteria
* The observable behavior that proves the fix
## How to test
(Optional — include ONLY when the user explicitly asks for it. When present, follow
"How to test — writing guidance": exact app + URL, Network-tab steps, exact request/host,
response field + expected values.)
---
## Engineering Notes
(Optional, last — root cause, suspect code, links.)
Bugs a human cannot reproduce (infra / outages / race conditions)
If the repro is not something a person can perform on demand (an upstream outage,
a server restart, a timing race, corrupted state), do NOT write pseudo-repro steps.
Replace ## Steps to reproduce with ## What happened — a short plain-language
narrative of the incident and its user-visible impact ("During the X outage on
, some users experienced …"). Keep ## Expected / ## Actual focused on
symptoms. ## How to test lists only checks QA can actually perform; the technical
trigger conditions and any dev-only verification (logs, Redis, metrics) go under
## Engineering Notes.
Template: Spike
## Question
What we need to answer.
## Timebox
e.g. 2 days.
## Deliverable
Doc / decision / prototype / follow-up tickets.
How to test — writing guidance
## How to test is optional (include only when the user asks for it), but when present it
MUST be concrete enough that a QA tester who has never seen the code can follow it
step-by-step. Write it as a numbered list. Be specific, not vague — never just "open the
web app."
For any behavior observable in the UI or an API response, follow this pattern:
- Name the exact app the tester opens and its URL (e.g. the Practice app at
https://practice.inkblottherapy.com, the client web app, or the mobile app + which build). Say which environment (staging vs prod) and, if it matters, which test account/role. - State any setup: data to pick (by opaque ID), feature flags to toggle, preconditions.
- If the check is in a network response, tell them to open browser dev tools (right-click → Inspect / F12) → Network tab and reload.
- Identify the exact request — method + full path, and the host it goes to
(e.g.
https://api.inkblottherapy.com/api/appointments/{id}) — and how to find it (filter box keyword). Then open the Response / Preview tab. - Name the specific field(s) to check and the expected value(s) for each state
(e.g.
video_provider=vonagewhen the flag is on,twiliowhen off). - Give the verify loop: toggle the flag / change the input, reload, confirm the value changes as expected. Add a second independent signal where possible (e.g. a related endpoint returning 200 vs 404).
Keep every step above the --- in language QA understands; push dev-only verification
(logs, Redis, metrics, DB queries) into ## Engineering Notes.
Authoring rules
- QA reads top-down and stops at the
---divider. Everything above it must be understandable without reading code or knowing the codebase. - Engineering Notes is the pressure valve: put ALL technical detail there, not interleaved through the ticket. When in doubt whether something is "too technical", move it to Engineering Notes.
- Summary (title): concise, imperative, specific. No trailing period.
- Do not bulk-backfill old/closed tickets. Reformatting open, not-yet-started tickets is fine when the assignee asks for it.
Jira specifics (inkblottherapy.atlassian.net)
- Projects are company-managed / classic (POD2 project id 10013).
- POD2 Story Points field is
customfield_10033(NOT customfield_10016). Verify the Story Points field per project via createmeta before setting points elsewhere. - Checkboxes (standard): always create/edit the description as ADF
(
contentFormat: "adf") and render## Acceptance criteriaas ataskListoftaskItemnodes (each withattrs.localIdandstate: "TODO") — this reliably produces real, tickable Jira checkboxes (verified by write-then-read-back). Do NOT rely on the markdown- [ ]path: it is inconsistent (sometimes a real task list, sometimes literal[ ]text). Only if ADF is truly unavailable, fall back to plain*bullets. - Collapsible Engineering Notes (optional): to keep technical detail tucked away by
default,
## Engineering Notesmay be rendered as an ADFexpandnode instead of a plain heading —{ "type": "expand", "attrs": { "title": "Engineering Notes" }, "content": [ ...block content... ] }, placed below the---divider. When you do this, the expand'stitlereplaces the heading (don't emit both a## Engineering Notesheading AND an expand titled the same). RequirescontentFormat: "adf": the markdown path silently flattensexpand, dropping the collapsible wrapper and hoisting its content inline. The collapse is purely visual in the Jira web UI — the content is always returned in full by the API (verbatim in an ADF fetch, hoisted inline in a markdown fetch), so any AI agent reading the ticket still sees the notes. Verify persistence by re-fetching withresponseContentFormat: "adf"(the tool echoes the saved description as markdown, which flattensexpand, so the markdown echo alone can't confirm the node saved).
Self-check before submitting
- Is the ticket free of PII/PHI (names, emails, phone numbers, health data, session content) — including screenshots, logs, and Engineering Notes?
- Does
## Acceptance criteriaexist in the description body, written as an ADFtaskList(real tickable checkboxes; plain*bullets only as the no-ADF fallback) with ≥1 testable item? - Could a non-technical reader (QA, PM, support) understand everything above the
---, including## How to testif present? - If
## How to testis present, does each step name the exact app + URL, the exact request/host to inspect, and the response field(s) with expected values (per the "How to test — writing guidance")? Is it omitted unless the user asked for it? - Is all technical detail (code paths, PRs, root cause, dev jargon) below the
---in## Engineering Notes? - Task/Story: is a user-story opening line used ONLY if a genuine end user exists?
Review pass
Before creating, run the Self-check as a graded review, not a mental yes/no. This catches the mistakes that quietly slip past a drafter.
Two modes:
- Self-review (always). After drafting, walk each Self-check item and grade it.
- Independent review (recommended for any non-trivial ticket). Have a SEPARATE agent/context run the same rubric adversarially against the draft. The author who wrote the ticket tends to rubber-stamp it; a fresh pass is where the real defects surface. Give the reviewer this skill's rules plus the draft, and ask for the structured output below.
Review output format:
- Compliance checklist — for each of the 6 Self-check items: PASS / FAIL / N/A with a one-line justification.
- Issues found — each tagged with severity and, where useful, a concrete suggested
rewrite:
- blocker — violates a hard rule (PII/PHI anywhere, acceptance criteria not in
the body as a taskList, developer-only detail above the
---) or is factually wrong. Must fix before creating. - should-fix — a convention or clarity gap that will mislead QA or misrepresent scope (e.g. the summary promises one thing but the acceptance criteria test another). Fix unless there's a deliberate reason not to.
- nice-to-have — wording/polish. Optional.
- blocker — violates a hard rule (PII/PHI anywhere, acceptance criteria not in
the body as a taskList, developer-only detail above the
- Verdict — "ready to create as-is" or the minimal changes needed first.
Recurring misses worth checking explicitly (each has bitten a real ticket):
- Hidden PII. A person's name riding along in a branch name, PR/commit link, or pasted log — hard-rule 1 applies to every section, including Engineering Notes.
- Title vs acceptance-criteria drift. The summary describes a narrower or wider behavior than the criteria actually verify. Make them agree.
- Acceptance criteria that restate implementation ("adds a CI job that runs RuboCop") instead of observable behavior ("the check fails when …").
## How to testpresent when nobody asked for it, or too vague for a QA tester who has never seen the code.