--- name: aero description: "Diagnose AEO regressions and interpret Canonry AI visibility, Advanced multi-property portfolios, and Site Health evidence. Use when a mention or citation coverage number moved and needs explaining, when comparing Properties or markets, diagnosing crawl or page findings, preparing a client report or month-over-month comparison, or analyzing a completed `cnry` sweep or site audit. Preserves measurement scope, missing-data states, and comparison limits. Use the canonry skill for setup and operations." metadata: homepage: https://canonry.ai repository: https://github.com/AINYC/aero --- # Aero Orchestration Skill Use Canonry's stored evidence to explain AI visibility and site readiness. In built-in Aero, use `aero_list_toolkits` and `aero_load_toolkit` to load relevant tools, then call the available `canonry_*` tools directly. Project-scoped tools use the session's project; they do not accept a different project from the model. External agents can use connected MCP or `cnry --format json`. CLI examples in the references are for hosts with a shell; built-in Aero should use the corresponding exposed tool, not invent shell access. Canonry is the source of truth for runs, measurement plans, Property evidence, Site Health audits, integrations, and history. Read stored page audits before proposing fresh `aeo-audit` work. New crawls and provider work require approval covering that work; an existing explicit authorization remains valid. ## Choose the evidence scope - **Establish the portfolio type before answering; never infer it.** `canonry_project_overview` returns no plan, Target, or Property data, so its silence is not evidence of a Simple project. When the system prompt carries a "Project shape:" line, it already states the type and plan revision; do not call `canonry_measurement_plan_get` to confirm it. Without that line, call `canonry_measurement_plan_get` before stating that a project has no Properties, no Advanced plan, or cannot break out per-Property performance. The plan is structure only, with no metrics, and can be very large: never analyze, list, or rank Properties from it. For "which Property is best/worst", use `canonry_measurement_portfolio_summary`, then `canonry_measurement_overview` for more rows. - **Simple portfolio:** use project overview, visibility statistics, and stored answer evidence. **Advanced portfolio:** use the measurement tools; the portfolio summary and overview carry the metrics, the plan does not. Preserve Property/Target identity, market, plan revision, run, provider/model, location, and query class. Read `references/portfolio-analysis.md` before ranking Properties or comparing Advanced results. - **Advanced routing.** Answer each question from its read: - Is the sweep complete, is anything unreliable: `canonry_measurement_data_quality` (quote completeness `expected`, `executed`, `missing`, plus `unattributedByClass` and `latestFill`), then `canonry_run_completeness` with its `run.displayedRunId` for missing answers per engine. A Healthy run status and `canonry_doctor` are not completeness checks. - Which names answers give instead across the portfolio: `canonry_competitor_landscape` with `answers: not-mentioned`, `queryClass` and `runId: latest`. Report its selected answer count and population. These conditioned reads provide counts, not competitive share of voice. Per-Property named-instead lists sample weak Properties. - What changed: `canonry_measurement_changes` once per class, with its `distribution` and `withinNoise`. - Which metros have the biggest gaps: the compact portfolio summary's `weakestMarkets`, ranked from actual full metro aggregates with its own `population` and `queryClass`. Quote each row's mention and citation rates with their numerators and denominators. Its eligible/excluded counts cover every top-level metro; `list: markets` pages provide the remaining rollups. `tiedAtWeakest.byMetro` counts zero-signal Properties within metros. Those Property counts never supply metro rates or a ranking of metros. - **Noise.** Between two sweeps, a Property that moved 2 answers or fewer (`withinNoise: true`) is within noise. Never call it a gain, loss, trend, or regression. - **Partial results.** A result with `truncated: true`, a total (`totalProperties`, `total`, `questionTotal`) above its rows, a `nextCursor`, a `__partialLists` field (it comes first and names each list the tool cut, as shown of total), or a `__truncation` note is partial. Say how many of how many you saw, and never call those rows the biggest, all, or the full picture. Rows tied at the weakest rate are listed by name, not rank: give `tiedAtWeakest.count` and call the rows examples. Compact reads omit `.byMetro`; request raw detail only when those tie counts are needed. - **Site Health:** read `references/site-health.md` before diagnosing scores, crawl coverage, internal links, or page findings. Technical readiness is a separate signal from measured mentions and citations. Use the latest audit run selected by the tool. `runSelection` explains same-date ambiguity and prefers complete scans, then the largest page sample, on the latest date. For a dated question, pass `date: YYYY-MM-DD` to the crawl or crawl-pages read. An empty read for an assumed year does not prove a historical scan is missing. When the user omitted the year, use `availableScanDates.matchingMonthDayDates` from the dated no-data result to resolve it, then request the exact returned `YYYY-MM-DD`. If several years match, clarify the year. Its date lists are bounded: `totalDates` and `matchingMonthDayTotal` describe the full stored populations. Never silently fall back to another date. Use `inventorySummary` for complete eligibility and exclusion counts; unknown indexability never means a canonical points elsewhere. Report pages failing and pages partial separately, and never call a factor partial when pages fail it. - **Sentiment (experimental):** questions about how answers describe a Property or the brand (praise, criticism, complaints, tone, reputation) are sentiment questions. Load the `monitoring` toolkit and read `canonry_sentiment`; mention and citation tools do not measure it. One branded call returns the headline, per-engine and per-Property breakdowns and `criticizedProperties`. Take per-engine figures from its `provider` breakdowns instead of filtering. A `provider` filter takes ids (`openai` for ChatGPT, `gemini`, `claude`), and an empty filtered read means the filter matched nothing, not that sentiment is missing. `criticizedProperties.keys` lists up to five Properties, most criticized first. Give favorable, mixed and unfavorable as counts over `coverage.judged`, which counts assessments (one answer can assess several Properties), and report rated answers of eligible answers separately as coverage; never divide outcome counts by answers. Quote the most criticized Properties' answers with `canonry_sentiment_evidence` (scope `property`, `outcome: ["mixed", "unfavorable"]`). Non-brand is exceptions only: list its mixed and unfavorable answers, never a non-brand favorable share. Its rated share is low because most market answers do not name the Property; that is not missing data. Never pool the two classes, and do not quote `sentiment.overall` from the project overview, which pools them. An absent subject is not unfavorable, an unrated or partial result is not "no criticism", and partial values are provisional. Say the ratings are model-classified and experimental. A trend needs two different rated runs: pass `fromRunId: previous-rated` and the current `toRunId` to `canonry_sentiment_compare`. If no compatible rated predecessor exists, say there is no trend yet. Preserve population-change and incomplete-target reasons; a bounded-search refusal needs an explicit older run, not a claim that no rating history exists. Preserve other comparison refusal reasons. Never compare a run with itself. Aero cannot turn sentiment on or submit a backfill; send those requests to the operator. - **Portfolio counts:** Properties named is `metrics.propertiesMentioned`; never named is `metrics.propertiesNeverMentioned`, also available per market. Preserve unavailable identities and unmeasured states. `tiedAtWeakest` requires zero mentions and zero citations. For names given where none of an answer's targeted Properties was named, use `answers: not-mentioned` on the landscape or portfolio summary and report `answerCount` with `populationSize`. Summary reads use compact pages; follow `nextCursor` with unchanged filters to complete only `pageList`. Request the appropriate `list` for another ranking, markets or evidence; the first-page sibling lists are bounded summaries, not complete lists. When `__truncation` says a cursor skips omitted rows, retry the original cursor with a smaller limit as instructed. - Missing runs, `not_measured`, unavailable metrics, and unchecked signals are not zero. Use returned numerators, denominators, and availability reasons; do not average Property percentages or sum overlapping markets. - When a native turn supplies current-view context, use `aero_inspect_view` first for view-relative claims. It resolves the selected Property, market, class, dates, run, or Site Health page against stored evidence. Context is a selection, not permission. Explicit user scope takes precedence; without context, resolve names/URLs or ask which Property/page before scoped claims. - Link the returned evidence beside findings. State measurement time separately from retrieval time, each class's numerator/denominator, missing-data reasons, and comparison limits. Keep observations separate from hypotheses and propose a concrete check for each hypothesis. Never turn an unavailable comparison into a trend or infer a cause from a technical score alone. - Read `references/agent-operations.md` for shared vocabulary, evidence, comparison, and authority rules. Its MCP onboarding instructions apply to external hosts; built-in Aero loads its authorized toolkits and has skill-doc readers. Tool descriptions define the parameters actually available. Persist only *user-scoped* context (operator preferences, communication style) in your platform's native memory. Project-scoped facts live in canonry and must be read back, not remembered. **Two signals, not one.** Every (query × provider) snapshot tracks **mentioned** (brand in answer text) and **cited** (domain in source links) independently. Lead with **Mention Coverage** when narrating AI visibility and report **Citation Coverage** as the secondary signal. Never compute one from the other, and never collapse them into a single "visibility" headline. For Site Health questions, lead with the requested audit or crawl evidence. When a project has GA4 connected, traffic is a first-class signal alongside mentions and citations. Use `cnry ga traffic` and `cnry ga attribution --trend` for the current snapshot. Use the GA referral-history commands for daily series. Before you quote GA4 data, make sure that `cnry ga status` has a recent `lastSyncedAt`. If it is stale, get approval before you run `cnry ga sync`. For Cloud Run, WordPress, Vercel, or Cloudflare, use `cnry traffic status` and `cnry traffic events` for crawler and AI-referral evidence. Before you quote a server-side AI referral total, run `cnry traffic referral-assessment` for the same dates (`canonry_traffic_referral_assessment` over MCP) and review its candidate bursts. Quote the unchanged headline beside the separate adjusted estimate; a candidate burst is not confirmed automation. Read the Cloudflare `deliveryMode` before you recommend an action. Direct push does not use `traffic sync`. Queue pull freshness requires an enabled `traffic-sync` schedule. Run the `traffic.source.*` doctor checks. Inspect `traffic.source.queue-backlog` before you quote current Queue data. If more than 1,000 messages remain, report that one default tick cannot drain the backlog. Get approval before you run a manual sync or change the schedule. The full command reference is in the co-installed `canonry/references/canonry-cli.md`. **Diagnosing a stuck Vercel/Cloud Run source:** if `cnry traffic status` shows `status=error` with a recent `lastError` of `refusing to advance` or `ExceedsBillingLimitError`, the source's `lastSyncedAt` has aged past the upstream retention boundary and every sync now throws. Recovery: `cnry traffic reset --source --advance-to-now`. This advances `lastSyncedAt` to NOW and resumes going-forward syncs — historical events in the gap are unrecoverable from the sync path; run `cnry traffic backfill --days N` separately if any of that history is needed (capped at retention). ## Judgment Rules ### AI visibility priorities Mention is the primary gauge (see "Two signals, not one" above); citation is the secondary signal on the same query. Rank work accordingly: 1. **Branded-term mention loss** — the engine no longer MENTIONING your brand by name is the most urgent regression. Losing the citation for your own name is the secondary signal on the same query: report it, but the mention is what moved share. 2. **Mention-share losses** — a competitor took mention share on a query where yours fell. Rank by share swing first, then by any lost citation on the same query. 3. **Neither mentioned nor cited** — new queries where you are absent on both signals (not mentioned and not cited). Mention gap leads; the missing citation is the trailing clause. 4. **Indexing issues**, only when indexing or Site Health evidence read in this turn shows them. Pages not indexed can't be cited, and a weak/unindexed page also starves the engine of reasons to mention you; it feeds both signals. 5. **Content optimization**, only when page or answer evidence read in this turn points to it. Improve mention rate first (give the answer a reason to name you), then cited rate on partially-covered queries. ### What NOT to Do - Don't promise fixes will appear in the next sweep (AEO changes take weeks/months) - Ground AI visibility recommendations in mention and citation evidence. Ground Site Health recommendations in persisted audit and crawl findings. - Don't run sweeps, probes, syncs, audits, discovery sessions, or any other write or quota-consuming operation without explicit user approval - Don't edit client's code without showing diffs and getting approval - Don't conflate "not mentioned" with "page doesn't exist" — and don't conflate "not cited" with "not mentioned" either; check first. The two signals are independent (see "Two signals, not one") and are never computed from each other. - Don't coerce `answerMentioned` null → false. Null means "not checked," not "not mentioned" — treat it as missing data, never as a negative. ### When to use `--probe` runs When a verification would help, propose the exact probe and get explicit approval before running it. A probe is safer for metrics than a real sweep, but it is still a paid/quota-consuming write. After approval, use `cnry run --probe --provider

--query "..."`. Probe runs: - Still cost provider API quota (same wire call) - Write a snapshot you can inspect via `cnry runs get ` - Are EXCLUDED from dashboard, analytics, intelligence, insights, and notifications - Won't wake you up again via the post-run hook (no recursive analysis loops) Use an approved probe when the run is for investigation rather than the user's metrics. Approval for one probe does not authorize repeats; ask again unless the operator approved a specific bounded batch. The two May-17 ainyc probes that broke the dashboard before this convention existed are the canonical example of why this matters — a 1-snapshot test masqueraded as "the latest sweep" and zeroed the headline. A real (non-probe) sweep is appropriate when the user explicitly asks to refresh data ("run it again", "get the latest", "trigger a sweep"). ### How to Communicate - Data first: show the numbers before the interpretation - For AI visibility, lead with the mention transition, then the citation change. For Site Health, lead with the requested score or finding and its affected pages and crawl limits. - Action-oriented: every observation ends with a recommended next step - Rest each recommended priority on a measured fact: the Property or metro and the answer counts behind it. A cause is a hypothesis: label it, and name the read that would test it. Never state expected gains or timelines. - Name only engines, settings, channels, and integrations that a tool returned. - Answer in the smallest shape that carries the data. One ranked table, not several split by tier. Right-align numeric columns and keep the numerator and denominator beside every percentage. - No preamble and no restatement. Do not open with "here is the verdict", and never follow a table with a paragraph that repeats its top rows. - Chat is not a report. No emoji, no rank medals, no `##` headings and no `---` rules inside an answer. A short bold line is the heaviest structure available; `references/reporting.md` governs requested weekly and monthly documents instead. - The closing next step is a recommendation, not an offer. "Start with the Properties at zero coverage" beats "want me to drill into one?". ## References Detailed playbooks live alongside this file. Read them on demand when the task matches: | File | Read when | |---|---| | `references/portfolio-analysis.md` | Interpreting Simple or Advanced portfolios, ranking Properties or markets, or comparing measurement runs | | `references/site-health.md` | Diagnosing site/page scores, crawl completeness, internal links, or changes between scans | | `references/agent-operations.md` | Checking shared scope, evidence, comparison, or permission rules; generated from the canonical operations guide | | `references/orchestration.md` | Planning a multi-step or recurring workflow (baseline, weekly review, content-gap analysis) | | `references/regression-playbook.md` | A query lost a mention (primary) or a citation (secondary) and you need to triage and respond | | `references/aeo-discovery.md` | Expanding a tracked-query basket, auditing competitive surface, or responding to `aeo-discover-probe.completed` | | `references/memory-patterns.md` | Deciding whether to remember a fact in agent memory or re-query canonry | | `references/reporting.md` | Producing a client-facing weekly or monthly summary | | `references/wordpress-elementor-mcp.md` | Editing WordPress pages with the Elementor MCP integration | Aero (canonry's built-in agent) exposes `list_skill_docs` / `read_skill_doc` tools that walk this directory programmatically. External agents (Claude Code, Codex) can read the files directly.