|
| 1 | +--- |
| 2 | +name: breakdown-perps-tickets |
| 3 | +description: Interactively break a perps product requirement into split, dispatch-ready technical tickets across MetaMask Core, its release, Mobile, and Extension. Use when a product manager (or a codebase-aware Claude acting for one) has a perps bug or feature and needs engineering-grade tickets, correctly routed now that @metamask/perps-controller is the Core source of truth. Triages where the change actually lives, emits only the applicable layer tickets with dependency links, and enforces token-efficient, signal-over-noise tickets agents can act on directly. |
| 4 | +maturity: experimental |
| 5 | +--- |
| 6 | + |
| 7 | +# Breakdown Perps Tickets |
| 8 | + |
| 9 | +Turn one perps product requirement into the **minimum set of technical tickets**, |
| 10 | +each routed to the right layer and written for direct agent ingestion. You have |
| 11 | +codebase access — use it to decide the split from the actual code, not guesswork. |
| 12 | + |
| 13 | +## When To Use |
| 14 | + |
| 15 | +- A PM (e.g. via a codebase-aware Claude) has a perps bug or feature and wants |
| 16 | + tickets engineering can dispatch as-is. |
| 17 | +- A requirement may span Core logic and one or both clients, and you need it |
| 18 | + split correctly instead of filed as one vague ticket against one repo. |
| 19 | + |
| 20 | +This is the **second pass**: the PM states *what's broken / expected* (no |
| 21 | +implementation); this skill does the technical breakdown + routing. It converts |
| 22 | +a bug or EPIC into engineering task tickets — it does not author initiatives/EPICs. |
| 23 | + |
| 24 | +Not for: pure investigation/spikes (narrow to a concrete behavior first), or |
| 25 | +non-perps work. |
| 26 | + |
| 27 | +## Operating principle: signal over noise |
| 28 | + |
| 29 | +The tickets you emit are consumed by autonomous agents. **Every word costs |
| 30 | +inference and dilutes focus.** Write the minimum that lets an agent reproduce and |
| 31 | +fix — no preamble, no restated context, no hedging. |
| 32 | + |
| 33 | +- 2-3 sentences per field, max. Cut anything an agent can derive from the code. |
| 34 | +- One concern per ticket. Split multi-bug / multi-layer requests. |
| 35 | +- Concrete > narrative: a route, a component, a testable assertion — not a story. |
| 36 | +- No screenshots-as-spec, no Figma links, no "investigate and fix", no "see recording". |
| 37 | +- If you can't state the expected behavior in one testable line, the ticket isn't ready — ask. |
| 38 | + |
| 39 | +## The layer model |
| 40 | + |
| 41 | +`@metamask/perps-controller` lives in **Core**; Mobile and Extension consume it |
| 42 | +(`"@metamask/perps-controller": "^9.x"`). A perps change can touch up to four |
| 43 | +layers, in dependency order: |
| 44 | + |
| 45 | +1. **Core** — change in `@metamask/perps-controller` (shared logic / source of truth). |
| 46 | +2. **Core release** — bump + publish the package so clients can pull it. *Separate ticket; blocks the clients.* |
| 47 | +3. **Mobile** — bump the dep + Mobile UI/integration work. |
| 48 | +4. **Extension** — bump the dep + Extension UI/integration work. |
| 49 | + |
| 50 | +Emit **only the layers that apply**. Most pure-UI bugs are client-only (no Core |
| 51 | +chain). Anything touching shared business logic (pricing, order/position math, |
| 52 | +stream transforms, validation, **analytics event constants**) is Core-first → |
| 53 | +release → clients. |
| 54 | + |
| 55 | +### Dependencies & validation gating |
| 56 | + |
| 57 | +Chain the tickets with **Jira "blocks / is blocked by"** links — and the gate is |
| 58 | +real, not cosmetic: |
| 59 | + |
| 60 | +- Core **blocks** Core-release **blocks** each client ticket. |
| 61 | +- A client ticket **cannot be validated or closed until the Core release is |
| 62 | + published AND the client has bumped `@metamask/perps-controller` to it.** Make |
| 63 | + that the client ticket's first acceptance line. |
| 64 | +- Set the link on every emitted ticket (`is blocked by` → the upstream). |
| 65 | + |
| 66 | +## Workflow (interactive) |
| 67 | + |
| 68 | +0. **Confirm repos (once, up front).** Triage is done *from the code*, so you |
| 69 | + need the checkouts. Ask the user to confirm the local paths for the three |
| 70 | + repos before analyzing — don't assume; they differ per machine and reviewer |
| 71 | + checkouts often live at `*-ref` paths: |
| 72 | + - **Core** (`@metamask/perps-controller` at `packages/perps-controller`) |
| 73 | + - **Mobile** |
| 74 | + - **Extension** |
| 75 | + If any is missing, say which and proceed only against the ones you have |
| 76 | + (e.g. client-only triage without Core). Don't hardcode paths into tickets. |
| 77 | + |
| 78 | +1. **Intake.** Read the requirement. Ask only the questions you can't answer from |
| 79 | + the code (expected behavior as a testable line, affected surface, required |
| 80 | + wallet state). Don't ask what the codebase already tells you. |
| 81 | + |
| 82 | +2. **Triage the layer — from the code.** Decide where the root cause/change lives: |
| 83 | + - Shared logic (controller state, math, stream/data transforms, validation) |
| 84 | + → **Core** + release + affected clients. |
| 85 | + - Rendering/formatting/navigation specific to one app → that **client only**. |
| 86 | + - Use `knowledge/architecture.md` and `knowledge/mobile-extension-map.md` to |
| 87 | + confirm whether a screen/util exists on both clients or diverges. Mobile is |
| 88 | + source of truth for behavior. |
| 89 | + - **Watch for hidden Core dependencies.** A task can look client-only but |
| 90 | + need a shared capability that lives in Core — most commonly a **new |
| 91 | + analytics event/property** (source of truth: `@metamask/perps-controller`, |
| 92 | + `packages/perps-controller/src/constants/eventNames.ts` + the metametrics |
| 93 | + reference doc), but also new controller state, selectors, or shared |
| 94 | + types/constants. If the client must emit a value/type the published package |
| 95 | + doesn't expose yet, it's Core-first. Grep the package before calling it |
| 96 | + client-only. |
| 97 | + - State your routing decision and the evidence (file/package) in one line. |
| 98 | + |
| 99 | +3. **Decide the split.** Map to the minimum ticket set: |
| 100 | + - Client-only bug → 1 client ticket (or 2 if both clients diverge from spec). |
| 101 | + - Shared-logic change → Core ticket → Core-release ticket → 1 ticket per |
| 102 | + affected client (each: dep bump + that client's UI/integration). |
| 103 | + - Don't create a layer ticket with no real work in it. |
| 104 | + |
| 105 | +4. **Emit the tickets** in the format below, with explicit dependency links, and a |
| 106 | + one-line breakdown summary at top (what split you chose and why). |
| 107 | + |
| 108 | +## Hidden Core dependencies & the interim-constant pattern |
| 109 | + |
| 110 | +The classic trap: a single client task that secretly needs a Core change first — |
| 111 | +most often **new analytics events**. Perps event constants are owned by |
| 112 | +`@metamask/perps-controller` (`.../constants/eventNames.ts`) + the metametrics |
| 113 | +doc; a client can't use a typed value the published package doesn't expose. |
| 114 | + |
| 115 | +Two ways to sequence it — pick by urgency, and **state which you chose**: |
| 116 | + |
| 117 | +- **Interim-constant decoupling (preferred when the client can't wait).** Client |
| 118 | + ships now with a *local interim constant* (marked TODO → the Core ticket), so |
| 119 | + delivery isn't blocked. Then Core adds + publishes the constant, and a client |
| 120 | + follow-up replaces the local copy with the typed value and removes the TODO. |
| 121 | + → **3 tickets** (client feature → core → client replace). |
| 122 | +- **Strict gating.** Client is blocked until the Core release lands. Fewer |
| 123 | + tickets, slower delivery. |
| 124 | + |
| 125 | +Real example — the shape to emit (TAT-3398 / TAT-3429 / TAT-3430): |
| 126 | + |
| 127 | +- `[mobile] Enable RoE sign toggle on Auto Close TP/SL` — feature; ships an |
| 128 | + interim local `tpsl_roe_sign_toggled` constant with a TODO. |
| 129 | +- `[core] Add tpsl_roe_sign_toggled + roe_sign to @metamask/perps-controller` — |
| 130 | + add to `eventNames.ts`, update the metametrics doc, **cut & publish**. |
| 131 | + *(folds the Core-release step in, or split it out as its own ticket.)* |
| 132 | +- `[mobile][extension] Replace local tpsl_roe_sign_toggled constant with the |
| 133 | + typed value` — bump the dep, drop the local constant + TODO. **Blocked by** the |
| 134 | + Core ticket. AC: no bespoke string literal remains; analytics uses the typed |
| 135 | + constant. |
| 136 | + |
| 137 | +## Ticket format (per layer, agent-ingestion) |
| 138 | + |
| 139 | +Keep every field tight. Pull routes/components from `knowledge/screens.md` and |
| 140 | +`knowledge/mobile-extension-map.md`; pull number rules from |
| 141 | +`knowledge/formatting-rules.md` — don't restate them. |
| 142 | + |
| 143 | +**Title** — `[core|core-release|mobile|extension] <one-line outcome>` |
| 144 | + |
| 145 | +**What / change** — actual behavior (bug) or the capability to add (feature). 1-2 sentences. |
| 146 | +**Expected (acceptance criteria)** — **numbered** testable "when X, then Y" lines; the |
| 147 | +downstream agent turns these directly into its AC matrix + recipe. Tag each with a proof |
| 148 | +mode so it knows how to verify: `[state]` (controller/store value), `[visual]` (rendered |
| 149 | +UI), `[mixed]`. E.g. `AC1 [visual] When a Long position is open, the size shows its USD value.` |
| 150 | +**Affected** — package/route/component (e.g. `@metamask/perps-controller` symbol, or `perps-order-entry-page`). Cite the real path. |
| 151 | +**Pre-conditions** — required wallet/app state (unlocked, open BTC position, etc.). Only the ones that apply. |
| 152 | +**Depends on** — upstream ticket(s) via Jira `is blocked by` (every client ticket is blocked by the Core-release; a "replace interim constant" ticket is blocked by the Core ticket). |
| 153 | + |
| 154 | +Layer specifics: |
| 155 | +- **Core**: name the controller behavior + the symbol/file. Acceptance = controller-level outcome (unit-testable). |
| 156 | +- **Core release**: title `[core-release] bump @metamask/perps-controller → <target version>`; body = "publish containing <core ticket>; clients bump to it." Depends on the Core ticket. |
| 157 | +- **Mobile / Extension**: first line = "bump `@metamask/perps-controller` to <version> (from <release ticket>)", then the client-side UI/integration work + acceptance. For number display, state the *semantic* ("shows USD value of position"), never "2 decimals" — precision is range-adaptive (see formatting-rules). |
| 158 | + |
| 159 | +## Quality bar (reject before emitting) |
| 160 | + |
| 161 | +- No steps / no affected component / no testable acceptance line → not ready; ask. |
| 162 | +- A ticket that just says "investigate" → narrow it or drop it. |
| 163 | +- Same fix needed on both clients but only one ticket → split. |
| 164 | +- A Core change with no release + client tickets → incomplete chain. |
| 165 | +- Verbose restated context the agent can read from code → cut it. |
| 166 | + |
| 167 | +## References (read installed, don't duplicate) |
| 168 | + |
| 169 | +- `knowledge/architecture.md` — where perps logic lives across Core/clients. |
| 170 | +- `knowledge/mobile-extension-map.md` — screen/route/component parity + divergences. |
| 171 | +- `knowledge/screens.md` — route/component names for the "Affected" field. |
| 172 | +- `knowledge/formatting-rules.md` — perps number/precision rules for acceptance criteria. |
| 173 | +- `knowledge/shared-package-analysis.md` — duplicated utilities to check both sides. |
| 174 | +- Related skills: `fix-perps-bug` (implement a client fix), `review-perps-pr` (review the resulting PRs). |
0 commit comments