← Files Seal CopilotARCHIVED FILE
skills/diagnose-drop/SKILL.md
5.68 KB · Oct 4, 2026 · 12:28 UTC
--- name: diagnose-drop description: > Root-cause diagnosis for a drop or spike in Sealmetrics metrics. Trigger on: "why did conversions drop", "why did sales fall", "traffic spiked, why", "what happened yesterday/this week", "qué ha pasado con", "revenue is down", or any cause-seeking question about a metric change. argument-hint: "[metric] [period]" short-description: 'Root-cause diagnosis of a drop or spike. Use for "why did conversions drop", "sales fell", "traffic spiked, why", "what happened this week", "qué ha pasado con", "revenue is down".' --- # Diagnose Drop (or Spike) Before writing your answer, read `examples/output.md` in this skill directory and match its density, structure and tone. It is the reference for what a good run of this skill looks like. Isolate the root cause of a metric change. Budget: ≤12 tool calls. Follow the cause hierarchy from `skills/seal-copilot/references/methodology.md` strictly — work down, stop at the first isolated cause. ## Procedure 0. Confirm the change: `get_overview` for the affected period with `compare=previous`. Totals are under `traffic` / `conversions`; the delta is `traffic_change` / `conversions_change`; the daily `*_series` show exactly which day it broke. If the user's claim is not visible in data, say so and show what you see instead. 1. **Bots/tracking:** `get_bot_stats(days=30)`. Read it with the three-outcome rule in `methodology.md` — an empty result means agent analytics is off, not 0% bots. **When bots are the cause the diagnosis is not finished until you have named the source.** Call `get_top_referrers` yourself — a single referrer at 90%+ bounce is the usual shape — and put its name in the cause statement. Do not tell the user to go and look: "it is bots" is an observation, "it is bots from cheap-traffic.example, block it at the CDN" is the finding they asked for. That call takes priority over every optional one, including anything gathered only to fill `profile.json`. Sudden near-zero on one page → check `get_pages(path_filter=...)` for a tag lost in a deploy. For a broken microconversion event (cart, checkout), compare `get_microconversions(period=30d, compare=previous)` per type — a single type collapsing while others hold is an instrumentation regression, not a demand problem. Cross-reference the `cart-watchdog` baseline if AtC is the affected metric. 2. **Channel:** `get_top_channels(period=this_week)` vs `get_top_channels(period=last_week)` (or the `this_month`/`last_month` pair for a monthly drop) — `get_top_channels` has no `compare`, so diff the pair yourself. All channels down evenly → jump to step 7. 3. **Campaign:** `get_campaigns(compare=previous, utm_source/medium filters)`. 4. **Landing/term:** `get_landing_pages(compare=previous)` and/or `get_terms(compare=previous)` filtered to the campaign. 5. **Device/country/browser:** `get_devices(compare=previous)` returns `by_device`, `by_browser` and `by_os` in one response, each row with `*_prev` twins — no separate browser or OS call needed. Add `get_countries(compare=previous)`. A collapse isolated to Safari, or to one iOS version, points at ITP or a rendering bug, not at demand. Country is timezone-derived — treat a country-only signal as directional. 6. **Product/SKU** (ecommerce only): if the drop concentrates on purchases but channels look uniform, run `get_property_breakdown` on the product identifier from `list_property_keys` for the affected vs prior period — a single SKU going out of stock or losing a top variant can move overall revenue noticeably. 7. **Seasonality — addressed, never skipped.** Re-run `get_overview` with `compare=yoy`: flat year over year means seasonal, so say so and stop. You may skip that call **only** when the isolation itself excludes seasonality — a single campaign or channel collapsed while its neighbours held flat, and no season does that to one line and not the others. Then say which of the two ruled it out. Seasonality does not get to go unmentioned because the cause looked obvious. 8. **Market-wide:** if nothing isolates, state it plainly. ## Output format All four sections are **mandatory**, in this order. A one-line summary is not an acceptable answer to this skill even when the cause is obvious: the user cannot act on "it was campaign X" without the evidence, the fix and the check. 1. **Cause statement** — one sentence: "The drop is isolated to [X]: [numbers]." State confidence (high/medium/low per sample size). 2. **Evidence chain** — the 2–4 data points that led there, with numbers. 3. **Action** — what to do about it, with estimated recovery impact. 4. **Verification** — what to re-check and when. Never omit this. A diagnosis the user cannot confirm in a week is an opinion, not a finding. Do not report how many tool calls you used. The budget is an internal constraint on you, not information for the user. If the change is a spike, validate bots first (rule 1) before celebrating. Never speculate beyond the data — if two causes remain plausible, present both with their evidence. --- Log the run in `<state-dir>/<site_id>/runs.jsonl` with exactly these fields and no others: `ts` (ISO timestamp, UTC), `skill`, `calls` (the number of Sealmetrics calls you made, counted), `budget` (this skill's documented ceiling, a number — `12` here), `verdict` (one of `on_track`, `watch`, `act`, `kpis_only`, `refused`, `error`, or the score for an audit), `scheduled` (boolean), `notes` (one line). The first real audit wrote `calls_used` and a free-text verdict because this footer said "calls used" in prose; the field names are the contract. Skip silently if the path is not writable.
SHA-256: 537e3feead2f3e2509ebef12f3617e111d032dde754c15351696773a6d8c3543