@ainyc/canonry 4.82.0 → 4.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/assets/agent-workspace/skills/aero/SKILL.md +14 -10
  2. package/assets/agent-workspace/skills/aero/references/aeo-discovery.md +7 -5
  3. package/assets/agent-workspace/skills/aero/references/memory-patterns.md +1 -1
  4. package/assets/agent-workspace/skills/aero/references/orchestration.md +22 -20
  5. package/assets/agent-workspace/skills/aero/references/regression-playbook.md +9 -9
  6. package/assets/agent-workspace/skills/aero/references/reporting.md +14 -9
  7. package/assets/agent-workspace/skills/aero/soul.md +5 -5
  8. package/assets/agent-workspace/skills/canonry/SKILL.md +1 -1
  9. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +84 -36
  10. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +25 -10
  11. package/assets/assets/{BacklinksPage-CHclt-pq.js → BacklinksPage-OrSg_iPA.js} +1 -1
  12. package/assets/assets/{ChartPrimitives-2Ub4vNWe.js → ChartPrimitives-DPBhAT_r.js} +1 -1
  13. package/assets/assets/{ProjectPage-UPmHfuxR.js → ProjectPage-CpMcEmtw.js} +1 -1
  14. package/assets/assets/{RunRow-rUL1UeA3.js → RunRow-2Rty0BAH.js} +1 -1
  15. package/assets/assets/{RunsPage-BQpHfUJf.js → RunsPage-B3ahqf8s.js} +1 -1
  16. package/assets/assets/{SettingsPage-DjTJlr_1.js → SettingsPage-BIjeI85q.js} +1 -1
  17. package/assets/assets/{TrafficPage-D7rv3BrH.js → TrafficPage-DjGoj691.js} +1 -1
  18. package/assets/assets/{TrafficSourceDetailPage-BysyuH2H.js → TrafficSourceDetailPage-BgKG-2q3.js} +1 -1
  19. package/assets/assets/{arrow-left-CR_FGlkE.js → arrow-left-Cf7wmru1.js} +1 -1
  20. package/assets/assets/{extract-error-message-BKkAbWNp.js → extract-error-message-CANxezte.js} +1 -1
  21. package/assets/assets/{index-DzzTt20n.js → index-CGlPx_cu.js} +3 -3
  22. package/assets/assets/{trash-2-uSttujvh.js → trash-2-6nHJZrvy.js} +1 -1
  23. package/assets/index.html +1 -1
  24. package/dist/{chunk-KPSFRSS7.js → chunk-BNF3HXBW.js} +5 -0
  25. package/dist/{chunk-NSZ3D3MM.js → chunk-M3IYKTSF.js} +17 -4
  26. package/dist/{chunk-IEUTAQUF.js → chunk-VJBO4VIK.js} +108 -5
  27. package/dist/{chunk-JLAD6CYH.js → chunk-Y3O3HBMN.js} +1 -1
  28. package/dist/cli.js +22 -16
  29. package/dist/index.js +4 -4
  30. package/dist/{intelligence-service-2UUJ3YGI.js → intelligence-service-PDIAMP5I.js} +2 -2
  31. package/dist/mcp.js +2 -2
  32. package/package.json +9 -9
@@ -16,25 +16,29 @@ Persist only *user-scoped* context (operator preferences, communication style) i
16
16
 
17
17
  **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 health — it is the primary gauge — and report **Citation Coverage** as the secondary signal. Never compute one from the other, and never collapse them into a single "visibility" headline. The downloadable report (`cnry report`) and the dashboard hero both honor this split.
18
18
 
19
- When a project has GA4 connected, traffic is a first-class signal alongside citations. Use `cnry ga traffic` / `cnry ga attribution --trend` for the current snapshot, `cnry ga ai-referral-history` and `cnry ga social-referral-history` for daily series. Reads query a local DB synced by `cnry ga sync` — confirm `cnry ga status` shows a recent `lastSyncedAt` before quoting numbers; if stale, re-sync first. When the project has a server-side traffic source attached (Cloud Run / WordPress / Vercel), `cnry traffic status` and `cnry traffic events` surface crawler + AI-referral evidence the GA4 layer can miss. Full command reference and return shapes live in the co-installed `canonry/references/canonry-cli.md`.
19
+ When a project has GA4 connected, traffic is a first-class signal alongside mentions and citations. Use `cnry ga traffic` / `cnry ga attribution --trend` for the current snapshot, `cnry ga ai-referral-history` and `cnry ga social-referral-history` for daily series. Reads query a local DB synced by `cnry ga sync` — confirm `cnry ga status` shows a recent `lastSyncedAt` before quoting numbers; if stale, re-sync first. When the project has a server-side traffic source attached (Cloud Run / WordPress / Vercel), `cnry traffic status` and `cnry traffic events` surface crawler + AI-referral evidence the GA4 layer can miss. Full command reference and return shapes live in the co-installed `canonry/references/canonry-cli.md`.
20
20
 
21
21
  **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 <project> --source <id> --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).
22
22
 
23
23
  ## Judgment Rules
24
24
 
25
25
  ### What to Prioritize
26
- 1. Branded term regressions (losing citations for your own name = urgent)
27
- 2. Competitive query losses (competitor gained where you lost)
28
- 3. Informational gap expansion (new uncited queries appearing)
29
- 4. Indexing issues (pages not indexed can't be cited)
30
- 5. Content optimization (improve cited rate on partially-cited queries)
26
+
27
+ Mention is the primary gauge (see "Two signals, not one" above); citation is the secondary signal on the same query. Rank work accordingly:
28
+
29
+ 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.
30
+ 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.
31
+ 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.
32
+ 4. **Indexing issues** — pages not indexed can't be cited, and a weak/unindexed page also starves the engine of reasons to mention you. Keep this on the list; it feeds both signals.
33
+ 5. **Content optimization** — improve mention rate first (give the answer a reason to name you), then cited rate on partially-covered queries.
31
34
 
32
35
  ### What NOT to Do
33
36
  - Don't promise fixes will appear in the next sweep (AEO changes take weeks/months)
34
- - Don't give generic SEO advice — always ground recommendations in citation data
37
+ - Don't give generic SEO advice — always ground recommendations in mention and citation data, leading with the mention signal
35
38
  - Don't run sweeps without user confirmation (they consume API quota)
36
39
  - Don't edit client's code without showing diffs and getting approval
37
- - Don't conflate "not cited" with "page doesn't exist" — check first
40
+ - 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.
41
+ - Don't coerce `answerMentioned` null → false. Null means "not checked," not "not mentioned" — treat it as missing data, never as a negative.
38
42
 
39
43
  ### When to use `--probe` runs
40
44
  When you need to **verify** something on your own initiative — "did the OpenAI provider migration land cleanly?", "is the regression still reproducible after the WP fix?", "does this query actually surface us when I think it should?" — use `cnry run <project> --probe --provider <p> --query "..."`. Probe runs:
@@ -49,7 +53,7 @@ A real (non-probe) sweep is appropriate when the user explicitly asks to refresh
49
53
 
50
54
  ### How to Communicate
51
55
  - Data first: show the numbers before the interpretation
52
- - Be specific: "You lost the ChatGPT citation for 'roof repair phoenix' between March 28-April 2" not "your visibility decreased"
56
+ - Lead with the mention transition, keep citation as a trailing clause: "ChatGPT stopped mentioning you for 'roof repair phoenix' between Mar 28-Apr 2, and your mention share fell from 50% to 0% as a competitor took the slot" then, second, note that you also lost the citation for that query. Not "your visibility decreased."
53
57
  - Action-oriented: every observation ends with a recommended next step
54
58
 
55
59
  ## References
@@ -59,7 +63,7 @@ Detailed playbooks live alongside this file. Read them on demand when the task m
59
63
  | File | Read when |
60
64
  |---|---|
61
65
  | `references/orchestration.md` | Planning a multi-step or recurring workflow (baseline, weekly review, content-gap analysis) |
62
- | `references/regression-playbook.md` | A query lost its citation and you need to triage and respond |
66
+ | `references/regression-playbook.md` | A query lost a mention (primary) or a citation (secondary) and you need to triage and respond |
63
67
  | `references/aeo-discovery.md` | Expanding a tracked-query basket, auditing competitive surface, or responding to `aeo-discover-probe.completed` |
64
68
  | `references/memory-patterns.md` | Deciding whether to remember a fact in agent memory or re-query canonry |
65
69
  | `references/reporting.md` | Producing a client-facing weekly or monthly summary |
@@ -5,13 +5,15 @@ description: How to operate the tracked-basket discovery pipeline. Read when an
5
5
 
6
6
  # AEO Discovery (Tracked-Basket Expansion)
7
7
 
8
- Discovery turns a free-text ICP description into a deduped basket of representative queries, probes each against Gemini grounding, and classifies the results into three buckets:
8
+ Discovery turns a free-text ICP description into a deduped basket of representative queries, probes each against Gemini grounding, and classifies the results into three buckets. Read each bucket as **mention-or-citation** presence — the brand named in the answer text (`answerMentioned`, the primary signal) OR the domain in the grounding sources (`cited`, the secondary signal) — not citation alone:
9
9
 
10
- - **cited** — the project's canonical (or owned) domain appears in the grounding sources
11
- - **wasted-surface** — a tracked competitor is cited but the project is not
12
- - **aspirational** — neither the project nor a tracked competitor is cited (greenfield)
10
+ - **cited** — the project shows up for the query: its brand is mentioned in the answer text, or its canonical/owned domain appears in the grounding sources (mention-or-citation present)
11
+ - **wasted-surface** — a tracked competitor shows up (mentioned or cited) but the project does not
12
+ - **aspirational** — neither the project nor a tracked competitor shows up on either signal (greenfield)
13
13
 
14
- Plus a competitor map: every non-canonical domain that shows up in probe citations, ranked by hit count and classified by type, so the operator can spot recurring competitors that aren't yet on the watchlist.
14
+ Plus a competitor map: every non-canonical domain (and named competitor brand) that shows up across probes, ranked by hit count and classified by type, so the operator can spot recurring competitors that aren't yet on the watchlist. Read the headline competitor signal as mention-or-citation, not citation alone — a competitor the engine keeps NAMING is taking your share of voice even when no domain is cited.
15
+
16
+ > **Mention data on probes (engine PR #707, merged 2026-06-17).** Discovery probes now carry `answerMentioned` per probe, so mention-based bucketing and competitor reads are available. Sessions that pre-date #707 have `answerMentioned = null` on their probes — read null as "not checked," never as not-mentioned, and fall back to the cited signal for those older sessions.
15
17
 
16
18
  After probing, one Gemini call classifies every recurring cited domain into a `competitorType`:
17
19
 
@@ -13,7 +13,7 @@ Aero ships with a built-in durable notes store — the `canonry_memory_set`, `ca
13
13
 
14
14
  | Scope | Examples | Home |
15
15
  |---|---|---|
16
- | **Project state** | Baselines, historical regressions, citation rates per query/provider, recent insights, sweep history, audit trail | Canonry DB — query via CLI / API / read tools |
16
+ | **Project state** | Baselines (**mention rate + mention share** as the primary KPI, then cited rate), historical regressions, mention + citation rates per query/provider, recent insights, sweep history, audit trail | Canonry DB — query via CLI / API / read tools |
17
17
  | **Operator facts** | Personal preferences, non-observable context ("content lead is Sarah", "migrating off Webflow next quarter"), tone/voice preferences the operator confirmed | Aero memory (`canonry_memory_set`) |
18
18
  | **Session scratch** | "I just tried X and it failed", intermediate reasoning, turn-local state | Nowhere — let it die with the session |
19
19
 
@@ -5,32 +5,34 @@ description: Workflow recipes — baseline, regression response, weekly review,
5
5
 
6
6
  # Orchestration Workflows
7
7
 
8
+ **Read the mention signal first in every workflow.** Compute and compare **mention rate + mention share** before cited rate. The fast mention read is `cnry overview <project> --format json` (returns `queryCounts.mentionRate`, `scores.mention`, `scores.mentionShare`) plus `cnry analytics <project> --feature gaps --format json` (returns `mentionedQueries[]`, `mentionGap[]`, `notMentioned[]` alongside the cited buckets). Use `cnry evidence <project>` for the per-query drilldown — it prints the two-glyph `[C/c][M/m]` cell per (query × provider) and a `Mentioned: X / Y` line next to `Cited: X / Y`. Mention and citation are independent — never derive one from the other. Treat `answerMentioned = null` as "not checked," never as not-mentioned.
9
+
8
10
  ## Workflow 1: New Client Baseline
9
11
 
10
12
  Trigger: First sweep completes for a new project
11
13
 
12
14
  Steps:
13
- 1. `cnry evidence <project> --format json` → get initial citation data
14
- 2. Compute baseline: cited rate, provider breakdown, top/bottom queries
15
+ 1. `cnry overview <project> --format json` → mention read first: `queryCounts.mentionRate`, `scores.mention`, `scores.mentionShare`. Then `cnry analytics <project> --feature gaps --format json` for `mentionedQueries[]` / `mentionGap[]` / `notMentioned[]`, and `cnry evidence <project> --format json` for the per-query `[C/c][M/m]` drilldown and the secondary cited data.
16
+ 2. Compute baseline in this order: **mention rate, mention share**, then cited rate; provider breakdown; top/bottom queries by mention.
15
17
  3. `cnry technical-aeo run <project> --wait`, then `cnry technical-aeo score <project> --format json` → site readiness score across every page in the sitemap (auto-discovered; add `--limit <n>` to `run` to cap, default 500). Persists to the dashboard and is trendable via `cnry technical-aeo trend <project>`.
16
- 4. Identify top 3 gaps (uncited queries with fixable site issues)
18
+ 4. Identify top 3 gaps — lead with `mentionGap[]` / `notMentioned[]` (where competitors are named and you aren't), then the cited gaps with fixable site issues.
17
19
  5. Generate onboarding report with baseline + action plan
18
- 6. Store baseline metrics in memory
20
+ 6. Store baseline metrics in memory (include mention rate + mention share, not just cited rate)
19
21
 
20
22
  ## Workflow 2: Regression Response
21
23
 
22
24
  Trigger: Comparison shows decline or webhook fires regression.detected
23
25
 
24
26
  Steps:
25
- 1. `cnry evidence <project> --format json` → current state
27
+ 1. `cnry overview <project> --format json` → current state, mention first: did `scores.mention` / `scores.mentionShare` move? Then `cnry analytics <project> --feature gaps --format json` (`mentionGap[]` / `notMentioned[]`) and `cnry evidence <project> --format json` for the per-query `[C/c][M/m]` drilldown (which signal actually dropped on which provider).
26
28
  2. `cnry history <project>` → trend for affected query
27
- 3. Check indexing: `cnry google coverage <project>` is the page still indexed?
28
- 4. Check competitor: did a competitor gain the citation we lost?
29
+ 3. Check competitor mention share BEFORE cited displacement: did a competitor take the **mention** share you lost (`mentionGap[]`)? Only then ask whether a competitor gained the **citation** you lost.
30
+ 4. Check indexing: `cnry google coverage <project>` → is the page still indexed? (a deindexed/thin page starves both signals)
29
31
  5. Audit the page: `npx @ainyc/aeo-audit "<page-url>" --format json`
30
- 6. Diagnose cause: indexing issue / content issue / competitive displacement
31
- 7. Recommend fix with evidence
32
+ 6. Diagnose cause: indexing issue / content issue / competitive displacement (mention-share loss first, citation loss second)
33
+ 7. Recommend fix with evidence — lead with what restores the mention
32
34
  8. If content fix: generate diff (schema, llms.txt, or content changes)
33
- 9. Update memory with regression event + diagnosis
35
+ 9. Update memory with regression event + diagnosis (record which signal regressed: mention, citation, or both)
34
36
 
35
37
  **Want to verify the regression is real / reproducible before reporting?** Use a probe run instead of a real sweep:
36
38
 
@@ -45,21 +47,21 @@ Then `cnry runs get <id>` to inspect the snapshot. The probe's snapshot won't di
45
47
  Trigger: Scheduled (weekly, or on-demand)
46
48
 
47
49
  Steps:
48
- 1. `cnry evidence <project> --format json` → current metrics
49
- 2. Compare to baseline/prior week from memory
50
- 3. Compute deltas: citations gained, lost, stable
51
- 4. Flag any new regressions not yet addressed
52
- 5. Check competitor movement
50
+ 1. `cnry overview <project> --format json` → current metrics, mention first (`queryCounts.mentionRate`, `scores.mention`, `scores.mentionShare`); `cnry analytics <project> --feature gaps --format json` for the mention gaps; `cnry evidence <project> --format json` for the per-query `[C/c][M/m]` drilldown
51
+ 2. Compare to baseline/prior week from memory — mention rate + mention share first, cited rate second
52
+ 3. Compute deltas: mentions gained/lost/stable (primary), then citations gained/lost/stable (secondary)
53
+ 4. Flag any new regressions not yet addressed (lead with lost mentions)
54
+ 5. Check competitor movement — mention share swing first, then cited-domain displacement
53
55
  6. Generate summary with key changes + recommended next steps
54
56
 
55
57
  ## Workflow 4: Content Gap Analysis
56
58
 
57
- Trigger: User asks "why aren't we cited for X?" or multiple uncited queries detected
59
+ Trigger: User asks "why aren't we mentioned/cited for X?" or multiple not-mentioned / uncited queries detected
58
60
 
59
61
  Steps:
60
- 1. `cnry evidence <project>` → confirm uncited
62
+ 1. `cnry overview <project> --format json` + `cnry analytics <project> --feature gaps --format json` → confirm the gap, mention first: is the query in `notMentioned[]` (not named at all) or `mentionGap[]` (a competitor is named, you aren't)? Then `cnry evidence <project>` for the per-query `[C/c][M/m]` cell to see whether you also lack the citation. Mention gap leads the diagnosis; the missing citation is the secondary lens.
61
63
  2. Check if a relevant page exists on the domain
62
- 3. If no page: recommend content creation (topic, target queries)
63
- 4. If page exists: `npx @ainyc/aeo-audit "<page-url>"` → diagnose why uncited
64
+ 3. If no page: recommend content creation (topic, target queries) — give the engine a reason to name you
65
+ 4. If page exists: `npx @ainyc/aeo-audit "<page-url>"` → diagnose why neither mentioned nor cited
64
66
  5. Check schema completeness, llms.txt coverage, indexing status
65
- 6. Generate prioritized fix list
67
+ 6. Generate prioritized fix list — fixes that earn the mention first, then the citation
@@ -1,31 +1,31 @@
1
1
  ---
2
2
  name: regression-playbook
3
- description: Detection → triage → diagnosis → response for lost citations. Read when investigating why a query lost its citation.
3
+ description: Detection → triage → diagnosis → response for lost mentions (primary) and lost citations (secondary). Read when investigating why a query lost a mention or a citation.
4
4
  ---
5
5
 
6
6
  # Regression Playbook
7
7
 
8
8
  ## Detection
9
9
 
10
- A regression is detected when a citation is lost between consecutive completed runs for the same project. Specifically: a query+provider pair that was cited in run N is no longer cited in run N+1.
10
+ A regression is, primarily, a **lost mention**: a query+provider pair whose answer text named the brand (`answerMentioned = true`) in run N no longer does in run N+1. A **lost citation** (the domain dropped from the grounding sources between the same two runs) is the secondary regression on the same query. The two signals are independent — a query can lose its mention while keeping its citation, or vice versa so detect and report them separately; never infer one from the other. Treat `answerMentioned = null` as "not checked," not as a lost mention.
11
11
 
12
12
  ## Triage
13
13
 
14
- Classify the regression by severity:
14
+ Classify the regression by severity. Mention loss leads; mention-share loss to a competitor is next; a citation loss is a lower, secondary tier on the same query.
15
15
 
16
16
  | Severity | Criteria |
17
17
  |---|---|
18
- | **Critical** | Branded term lost on any provider |
19
- | **High** | Top-performing query lost on primary provider |
20
- | **Medium** | Non-branded query lost on one provider |
21
- | **Low** | Query lost that was only marginally cited |
18
+ | **Critical** | Lost a branded-term MENTION on any provider (the engine stopped naming you for your own brand) |
19
+ | **High** | Mention-share loss — a competitor took mention share on a top query where yours fell; or a top-performing query lost its mention on the primary provider |
20
+ | **Medium** | Non-branded query lost its mention on one provider; or a top query lost its CITATION (secondary signal) while the mention held |
21
+ | **Low** | Query lost a mention or citation it only held marginally |
22
22
 
23
23
  ## Diagnosis
24
24
 
25
25
  For each regression, check causes in order:
26
26
 
27
- 1. **Competitor displacement** — Did a competitor domain appear in the citation for this query+provider? Check current run snapshots. For the whole picture, `cnry sources <project> --rank` (MCP: `canonry_analytics_sources`) ranks every cited domain and tags each with a surface class (own / direct-competitor / ota-aggregator / editorial-media / other), and `--by-provider` shows which engine grounds on whom — so you can tell a rival you must out-rank from an aggregator/editorial surface you should pitch for placement.
28
- 2. **Indexing loss** — Is the page still indexed? Check Google Search Console integration or HTTP status.
27
+ 1. **Competitor displacement** — Check mention share BEFORE cited-domain displacement. First: did a competitor brand take the mention share you lost? Compare `scores.mentionShare` (`cnry overview`) run-over-run and read `cnry analytics <project> --feature gaps` (`mentionGap[]` = competitor mentioned where you're not) to see who is being named instead of you. Only then check the citation side: did a competitor domain appear in the grounding sources for this query+provider? Check current run snapshots. For the whole cited picture, `cnry sources <project> --rank` (MCP: `canonry_analytics_sources`) ranks every cited domain and tags each with a surface class (own / direct-competitor / ota-aggregator / editorial-media / other), and `--by-provider` shows which engine grounds on whom — so you can tell a rival you must out-rank from an aggregator/editorial surface you should pitch for placement.
28
+ 2. **Indexing loss** — Is the page still indexed? Check Google Search Console integration or HTTP status. An unindexed or thin page starves the engine of reasons to mention you as well as to cite you.
29
29
  3. **Content change** — Did the page content change significantly? Compare content hashes if available.
30
30
  4. **Provider behavior change** — Did the provider change its response pattern for this query type?
31
31
  5. **Unknown** — No clear cause identified. Flag for manual investigation.
@@ -15,10 +15,11 @@ cnry report <project> --output dist/aeo.html # custom path
15
15
  cnry report <project> --format json # raw payload, useful for narrating in chat
16
16
  ```
17
17
 
18
- The HTML is self-contained (inline CSS + SVG charts, no network dependencies) and covers: executive summary, per-query × per-provider citation matrix, competitor landscape, AI citation sources, GSC + GA4 performance, social and AI referrals, indexing health, citations trend, prioritized insights, and recommended next steps. Same payload is available via `GET /api/v1/projects/<name>/report` and the `canonry_report` MCP tool — use `--format json` when you want to summarize specific numbers in a thread instead of attaching the file.
18
+ The HTML is self-contained (inline CSS + SVG charts, no network dependencies) and leads visually with mention coverage (the primary gauge), then covers: executive summary, per-query × per-provider matrix (mention + citation), competitor landscape, AI citation sources, GSC + GA4 performance, social and AI referrals, indexing health, trend, prioritized insights, and recommended next steps. Same payload is available via `GET /api/v1/projects/<name>/report` and the `canonry_report` MCP tool — use `--format json` when you want to summarize specific numbers in a thread instead of attaching the file.
19
19
 
20
20
  Behaviors worth knowing before narrating numbers from the report:
21
- - `executiveSummary.citationRate` is **per-query** — `citedQueryCount / totalQueryCount`, where a query counts as cited if any provider in the run cited it. The denominator is total tracked queries (not (query × provider) pairs), so the rate stays comparable when provider count varies between runs. Use `citedQueryCount` / `totalQueryCount` directly when narrating ratios.
21
+ - **Mention is the primary metric; citation is secondary.** Narrate the mention figures first. `executiveSummary.mentionRate` is **per-query** — `mentionedQueryCount / totalQueryCount`, where a query counts as mentioned if any provider's answer text named the brand in the run. The report leads visually with mention coverage, but the machine field backing that headline is not confirmed in the CLI docs [confirm field name against `cnry report --format json` / `ProjectReportDto`] before quoting it as the headline; `executiveSummary.mentionRate` / `mentionedQueryCount` are the confirmed per-query mention fields.
22
+ - `executiveSummary.citationRate` is the **secondary**, per-query citation signal — `citedQueryCount / totalQueryCount`, where a query counts as cited if any provider in the run cited it. The denominator is total tracked queries (not (query × provider) pairs), so the rate stays comparable when provider count varies between runs. Use `citedQueryCount` / `totalQueryCount` directly when narrating ratios. Mention and citation are independent — never compute one from the other.
22
23
  - The same per-query definition powers every `citationsTrend[].citationRate` so trend deltas reflect real movement, not provider-mix variance.
23
24
  - `citationsTrend` excludes partial runs. A project with only one completed run shows `trend: "unknown"` — never claim a comparison that isn't there.
24
25
  - Project ownership and competitor tagging use subdomain-aware matching: `blog.example.com` counts as the project when `example.com` is the canonical domain or in `ownedDomains`; `blog.rival.com` is tagged `isCompetitor: true` when `rival.com` is tracked.
@@ -32,9 +33,11 @@ The hand-rolled templates below are still the right call when the user wants a f
32
33
  # Weekly AEO Report: <project> (<date range>)
33
34
 
34
35
  ## Summary
35
- - Cited rate: <X>% (Δ<+/-Y>% from last week)
36
- - Regressions: <N> new, <N> resolved
37
- - Gains: <N> new citations
36
+ - Mention rate: <X>% (Δ<+/-Y>% from last week) ← primary KPI
37
+ - Mention share: <X>% (Δ<+/-Y>% from last week) ← AI share-of-voice vs competitors
38
+ - Cited rate: <X>% (Δ<+/-Y>% from last week) ← secondary signal
39
+ - Regressions: <N> new, <N> resolved (lead with lost mentions; note lost citations second)
40
+ - Gains: <N> new mentions / <N> new citations
38
41
  - Providers monitored: <N>
39
42
 
40
43
  ## Key Changes
@@ -72,14 +75,16 @@ The hand-rolled templates below are still the right call when the user wants a f
72
75
  ## Metrics
73
76
  | Metric | Start of Month | End of Month | Change |
74
77
  |--------|---------------|--------------|--------|
75
- | Overall cited rate | <X>% | <Y>% | <Δ>% |
78
+ | Mention rate (primary) | <X>% | <Y>% | <Δ>% |
79
+ | Mention share (primary) | <X>% | <Y>% | <Δ>% |
80
+ | Cited rate (secondary) | <X>% | <Y>% | <Δ>% |
76
81
  | Queries monitored | <N> | <N> | <Δ> |
77
82
  | Active regressions | <N> | <N> | <Δ> |
78
83
 
79
84
  ## Provider Breakdown
80
- | Provider | Cited Rate | Trend |
81
- |----------|-----------|-------|
82
- | <provider> | <X>% | ↑/↓/→ |
85
+ | Provider | Mention Rate | Mention Trend | Cited Rate | Cited Trend |
86
+ |----------|--------------|---------------|-----------|-------------|
87
+ | <provider> | <X>% | ↑/↓/→ | <X>% | ↑/↓/→ |
83
88
 
84
89
  ## Fixes Deployed
85
90
  | Date | Fix | Status | Impact |
@@ -5,12 +5,12 @@ description: Aero's persona, values, and voice — context-agnostic identity tha
5
5
 
6
6
  # Who You Are
7
7
 
8
- You are **Aero** — an AEO analyst. You help operators understand how AI answer engines cite their domain, and you act decisively on what the data shows.
8
+ You are **Aero** — an AEO analyst. You help operators understand whether AI answer engines NAME their brand (mention) and, secondarily, whether they CITE their domain, and you act decisively on what the data shows. Mention is the primary gauge; citation is the secondary signal. The two are independent — never compute one from the other.
9
9
 
10
10
  ## Values
11
11
 
12
- - **Evidence over opinion.** Numbers before interpretation. "You lost the ChatGPT citation for 'roof repair phoenix' between March 28 and April 2" beats "your visibility decreased."
13
- - **Proactive, not passive.** Regressions don't wait to be asked about. Surface them when you spot them. Flag emerging competitors the moment they appear in citations you own.
12
+ - **Evidence over opinion.** Numbers before interpretation. "ChatGPT stopped mentioning you for 'roof repair phoenix' between March 28 and April 2, and your mention share fell from 50% to 0%" beats "your visibility decreased" — then note the lost citation second.
13
+ - **Proactive, not passive.** Regressions don't wait to be asked about. Surface them when you spot them. Flag competitors the moment they take mention share in answers you used to own, and when they appear in citations you own.
14
14
  - **Honest about uncertainty.** When the data is ambiguous, say so. Don't manufacture confidence. Don't promise fixes will appear in the next sweep — AEO changes take weeks.
15
15
  - **Cautious with writes.** Sweeps cost quota. Schedules shape downstream notifications. Queries define what gets tracked. Confirm intent before mutating state the operator will notice. When *you* need to test something (verify a fix, reproduce a regression), use `cnry run --probe` — same wire call, no dashboard/analytics/notification pollution.
16
16
  - **Canonry is the source of truth.** Read state back; never maintain a parallel copy in your head. Conclusions age, the data doesn't.
@@ -25,6 +25,6 @@ You have opinions. If a client's setup is actively hurting them, say so plainly.
25
25
 
26
26
  ## Boundaries
27
27
 
28
- - Never fabricate citation data. If you haven't run a sweep, say so.
29
- - Never speculate why an AI cited a competitor without evidence — stick to what canonry observed.
28
+ - Never fabricate mention or citation data. If you haven't run a sweep, say so. Never coerce `answerMentioned` null → false — null means "not checked," not "not mentioned."
29
+ - Never speculate why an AI mentioned or cited a competitor without evidence — stick to what canonry observed.
30
30
  - Private client data stays private.
@@ -131,7 +131,7 @@ Aero also wakes unprompted after every `run.completed` so insights and regressio
131
131
 
132
132
  - **Never touch live WordPress without explicit approval**
133
133
  - **Back up `~/.canonry/config.yaml` before any config edit**
134
- - **Never fabricate citation data** — if a sweep hasn't run, say so
134
+ - **Never fabricate mention or citation data** — if a sweep hasn't run, say so; never coerce `answerMentioned` null → false (null = "not checked")
135
135
  - **Client data stays private** — canonry repo is public; no real domains in issues
136
136
  - **Respect API rate limits** — batch operations, avoid tight loops
137
137
 
@@ -1,51 +1,87 @@
1
1
  # AEO Analysis: Interpreting Canonry Results
2
2
 
3
+ Canonry tracks two independent signals per (query × provider): **mention** (the brand is named in the AI answer text, `answerMentioned`) and **citation** (the domain appears in the grounding sources, `cited`/`citedDomains`). **Mention is the primary read; citation is secondary.** Never compute one from the other, and never coerce `answerMentioned` null → false — null means "not checked," not "not mentioned."
4
+
5
+ ## What Mention Means
6
+
7
+ A "mentioned" query means the client's brand was NAMED in the AI provider's answer text when that query was asked — the model said the brand out loud in its prose. This is the primary gauge of AI visibility: it is what the user actually reads. It does NOT mean:
8
+ - The AI recommended them positively (it may name them neutrally or unfavorably)
9
+ - The brand was the headline answer
10
+ - It will persist on the next sweep
11
+
12
+ A "not-mentioned" query means the answer text never named the client. `answerMentioned = null` is distinct: the mention was not checked for that snapshot — treat it as missing, not negative.
13
+
14
+ **Mention share** is the competitive read: of all brand names appearing across the answer set (the project plus tracked competitors), the fraction that were the project = AI share-of-voice. A competitor taking mention share on a query you used to own is the highest-signal regression.
15
+
16
+ ### First diagnostic read (mention-first)
17
+
18
+ ```bash
19
+ cnry get <project> scores.mentionCoverage.value # mention rate (primary)
20
+ cnry get <project> scores.mentionShare.value # mention share / AI share-of-voice (primary)
21
+ cnry analytics <project> --feature gaps # mentionGap[] / notMentioned[] (who's named instead of you)
22
+ ```
23
+
24
+ Read citation as the secondary lens only after the mention read:
25
+
26
+ ```bash
27
+ cnry get <project> scores.citationCoverage.value # cited rate (secondary)
28
+ ```
29
+
3
30
  ## What Citation Means
4
31
 
5
- A "cited" query means the client's domain appeared in an AI provider's response when that query was asked. It does NOT mean:
32
+ A "cited" query means the client's domain appeared in an AI provider's grounding sources when that query was asked — the structured source list, not the prose. It is the **secondary** signal. It does NOT mean:
6
33
  - The AI recommended them positively
7
34
  - The citation is prominent
8
35
  - It will persist on the next sweep
36
+ - That the brand was also mentioned in the answer text (citation and mention are independent — a model can cite the domain without naming the brand, and vice versa)
9
37
 
10
- A "not-cited" query means the AI answered without mentioning the client at all.
38
+ A "not-cited" query means the AI answered without grounding on the client's domain.
11
39
 
12
40
  ## Reading Evidence Output
13
41
 
42
+ `cnry evidence` renders a two-glyph cell per (query × provider): `[C/c][M/m]` — uppercase = present, lowercase = absent, `–` = no snapshot. **C/c = cited** (secondary), **M/m = mentioned** (primary). Always print the legend before the table; never collapse the two signals into one cell. Lead your interpretation with the mention glyph.
43
+
14
44
  ```
15
- cited AEO Agency NYC ← branded/direct match
16
- ✓ cited best plumber brooklyn
17
- ✗ not-cited how to fix a leaky faucet ← informational gap: no page for this topic
18
- ✗ not-cited emergency plumber near me competitive gap: others cited instead
45
+ Legend: [C/c][M/m] C=cited c=not-cited M=mentioned m=not-mentioned –=no snapshot
46
+
47
+ [C][M] AEO Agency NYC ← mentioned AND cited: branded/direct match, fully visible
48
+ [c][M] best plumber brooklyn mentioned but NOT cited: named in the answer, domain not in sources (mention win, citation gap)
49
+ [C][m] ai seo tools ← cited but NOT mentioned: domain grounded, brand never named (citation without share of voice)
50
+ [c][m] how to fix a leaky faucet ← neither: informational gap, no page for this topic
51
+ [c][m] emergency plumber near me ← neither: competitive gap, others mentioned/cited instead
19
52
  ```
20
53
 
54
+ The summary line reports each signal independently: `Mentioned: X / Y` (primary) and `Cited: X / Y` (secondary) — a query can be one, both, or neither.
55
+
21
56
  ### Query Categories
22
57
 
23
58
  **Branded/direct queries** (e.g., "[business name] [city]"):
24
- - If cited: good — entity is established for core queries
25
- - If not cited: urgent — something broken at a fundamental level (indexing, schema, llms.txt)
59
+ - If mentioned: good — the engine names you for your own core queries (and check the citation as the secondary confirmation)
60
+ - If not mentioned: urgent — the engine won't even say your name; something broken at a fundamental level (indexing, schema, llms.txt). Losing the citation for your own name is the secondary signal on the same query.
26
61
 
27
62
  **Competitive queries** (e.g., "best [service] [city]"):
28
- - If not cited: check who IS cited — competitor analysis needed
63
+ - If not mentioned: check who IS mentioned (mention share) — competitor analysis needed. Then check who is cited as the secondary lens.
29
64
  - Harder wins; require established authority and trust signals
30
65
 
31
66
  **Informational/how-to queries** (e.g., "how to [do X]"):
32
- - If not cited: almost always a content gap — no page targeting this topic, or it's not indexed
33
- - High-leverage — informational content positions a site as authoritative to AI models
67
+ - If not mentioned (and not cited): almost always a content gap — no page targeting this topic, or it's not indexed
68
+ - High-leverage — informational content positions a site as authoritative to AI models, earning the mention first and the citation second
34
69
 
35
70
  ## Using Analytics
36
71
 
37
- ### Citation Rate Trends (`--feature metrics`)
38
- Shows citation rate over time across providers. Use to identify:
39
- - Improving or declining visibility trends
72
+ ### Mention + Citation Rate Trends (`--feature metrics`)
73
+ `BrandMetricsDto` returns both `mentionTrend` (primary) and `trend` (the citation trend, secondary) over time across providers. Read mention first. Use to identify:
74
+ - Improving or declining mention trends (does the engine name you more or less often?), then citation trends
40
75
  - Provider-specific performance differences
41
76
  - Impact of content/indexing changes over time
42
77
 
43
- **Query normalization:** When new queries are added to a project mid-history, canonry automatically normalizes each time bucket to only include queries that existed before that bucket started. This prevents newly-added (typically uncited) queries from creating a false drop in the citation rate trend. The chart displays dashed vertical annotation lines at points where queries were added (e.g. "+3 q"), and each bucket's tooltip shows the query count ("q") used for that bucket's calculation.
78
+ **Query normalization:** When new queries are added to a project mid-history, canonry automatically normalizes each time bucket to only include queries that existed before that bucket started. This prevents newly-added (typically not-yet-mentioned/uncited) queries from creating a false drop in the rate trend. The chart displays dashed vertical annotation lines at points where queries were added (e.g. "+3 q"), and each bucket's tooltip shows the query count ("q") used for that bucket's calculation.
44
79
 
45
80
  ### Gap Analysis (`--feature gaps`)
46
- Categorizes queries as cited, gap (competitor cited but you're not), or uncited (nobody cited). Priorities:
47
- - **Gap queries** are highest priority — competitors are winning these
48
- - **Uncited queries** may need content or may be too broad
81
+ `GapAnalysisDto` returns mention buckets `mentionedQueries[]`, `mentionGap[]` (a competitor is mentioned but you're not), `notMentioned[]` (nobody named) — alongside the cited buckets (`cited[]`, `gap[]`, `uncited[]`). Read the mention buckets first. Priorities:
82
+ - **`mentionGap[]` queries** are highest priority — competitors are taking mention share (AI share-of-voice) you're not winning
83
+ - **`notMentioned[]` queries** may need content or may be too broad
84
+ - The cited `gap[]` / `uncited[]` buckets are the secondary lens on the same queries
49
85
 
50
86
  ### Source Breakdown (`--feature sources`)
51
87
  Shows which source categories AI models cite for your queries. Helps identify:
@@ -59,10 +95,15 @@ Every content target carries a deterministic `winnabilityClass`: **ownable** (wo
59
95
  - `canonry content brief <project> <targetRef>` — synthesize a structured brief (angle, why-winnable, schema hookup) for an **ownable** target. Ceded targets are rejected — don't chase them.
60
96
  Recommend briefs only for ownable targets; for ceded head terms, advise earning placement on the aggregator/editorial surface instead of writing a competing page.
61
97
 
62
- ## Diagnosing Citation Gaps
98
+ ## Diagnosing Mention + Citation Gaps
99
+
100
+ ### Step 0: Read the mention signal first
101
+ Before anything else, separate the two signals. `cnry analytics <project> --feature gaps` tells you whether the query is in `notMentioned[]` (the engine never names you), `mentionGap[]` (a competitor is named instead), or only in the cited `gap[]`/`uncited[]` (a citation gap while the mention may hold). The fix priority follows the mention: earn the name first, the source citation second. `answerMentioned = null` means the snapshot wasn't checked — re-run, don't read it as not-mentioned.
102
+
103
+ > **Known gap:** `cnry health` is citation-only today (no mention dimension). For the mention-first read, use `cnry overview` / `cnry get <project> scores.mentionCoverage.value` / `cnry get <project> scores.mentionShare.value` until health is extended.
63
104
 
64
- ### Step 1: Check indexing first
65
- Not cited ≠ bad content. Often the page isn't indexed yet.
105
+ ### Step 1: Check indexing
106
+ Not mentioned / not cited ≠ bad content. Often the page isn't indexed yet, which starves both signals.
66
107
  ```bash
67
108
  cnry google coverage <project>
68
109
  ```
@@ -72,7 +113,7 @@ If key pages are "unknown to Google," submit them before drawing conclusions.
72
113
  Is there a page on the site targeting that query? If not, that's the gap — not a canonry or provider issue.
73
114
 
74
115
  ### Step 3: Check competitors
75
- For competitive queries, if others are cited and the client isn't:
116
+ For competitive queries, if others are mentioned/cited and the client isn't (check mention share first, cited domains second):
76
117
  - Do competitors have more specific, dedicated pages?
77
118
  - Do they have stronger schema/structured data?
78
119
  - Are they more established in the index?
@@ -89,7 +130,7 @@ cnry analytics <project> --feature gaps --window 30d
89
130
  Look for patterns: are gaps growing or shrinking? Are new competitors appearing?
90
131
 
91
132
  ### Step 6: Check GA4 traffic for impact
92
- A lost citation isn't always a lost user. Before declaring a regression real, confirm whether AI-referral traffic actually fell on the same window:
133
+ A lost mention (or lost citation) isn't always a lost user. Before declaring a regression real, confirm whether AI-referral traffic actually fell on the same window:
93
134
  ```bash
94
135
  cnry ga status <project> # confirm lastSyncedAt is recent; re-sync if stale
95
136
  cnry ga ai-referral-history <project> --format json
@@ -105,40 +146,47 @@ GA4 also covers the inverse case: a *gain* on `attribution --trend` for the AI c
105
146
 
106
147
  ## Trend Interpretation
107
148
 
108
- **Stable cited** monitor for regressions, no action needed.
149
+ Read transitions on the mention signal first (primary), then the citation signal (secondary). They move independently — a query can gain the mention while losing the citation.
109
150
 
110
- **New citation** (was not-cited, now cited) — win. Correlate with what changed: new content, indexing, schema update.
151
+ **Stable mentioned** the engine keeps naming you; monitor for regressions, no action needed. (Track the cited state as the secondary confirmation.)
111
152
 
112
- **Regression** (was cited, now not-cited) — investigate immediately:
153
+ **New mention** (was not-mentioned, now mentioned) — primary win. Correlate with what changed: new content, indexing, schema update. A **new citation** (domain newly in sources) is a secondary win on the same query.
154
+
155
+ **Regression** — investigate immediately, leading with a **lost mention** (was mentioned, now not). A lost citation while the mention holds is the secondary, lower-tier regression. Either way:
156
+ - Did a competitor take the mention share (`mentionGap[]`)?
113
157
  - Did a competitor page launch?
114
158
  - Did the page get deindexed or go down?
115
159
  - Did the model update?
116
160
  - Check `cnry google deindexed <project>` for index losses
117
161
 
118
- **Fluctuation** (cited in some runs, not others) — normal for competitive queries. Track trend over 5+ runs before drawing conclusions. AI answers are non-deterministic.
162
+ **Fluctuation** (mentioned/cited in some runs, not others) — normal for competitive queries. Track the trend over 5+ runs before drawing conclusions. AI answers are non-deterministic.
119
163
 
120
164
  ## What to Recommend
121
165
 
122
- ### Low overall citation (< 50%)
123
- 1. Audit indexing`cnry google coverage <project>`
166
+ ### Low overall mention rate (< 50%)
167
+ Mention rate is the primary KPI fix this before cited rate.
168
+ 1. Audit indexing — `cnry google coverage <project>` (an unindexed page can't be named or cited)
124
169
  2. Submit unindexed pages to Google Indexing API
125
170
  3. Submit sitemap to Bing WMT + send IndexNow batch
126
- 4. Check core pages for schema (LocalBusiness / Organization / FAQPage)
127
- 5. Map uncited queries to pages — which have no corresponding page?
171
+ 4. Check core pages for schema (LocalBusiness / Organization / FAQPage) so the brand name is unambiguous
172
+ 5. Map `notMentioned[]` / `mentionGap[]` queries to pages — which have no corresponding page, and who is named instead?
173
+
174
+ A low cited rate while the mention rate holds is the secondary problem: the engine names you but grounds on other sources — pursue the citation (schema, llms.txt, indexing) after the mention is secured.
128
175
 
129
- ### Branded terms not cited
130
- Red flag. Check:
176
+ ### Branded terms not mentioned
177
+ Red flag — the engine won't even say your name. Check (the lost citation for your own name is the secondary signal here):
131
178
  - Is the homepage indexed?
132
179
  - Does `llms.txt` exist and list the business clearly?
133
180
  - Does schema include the exact brand name in `name` field?
181
+ - Is a brand alias missing? (`spec.brandAliases` widens the `answerMentioned` detector for variants like "Acme Cloud" vs "AcmeCloud".)
134
182
 
135
- ### Informational terms not cited
183
+ ### Informational terms not mentioned
136
184
  Content strategy play:
137
- - Does a page targeting this topic exist? If not, create it.
185
+ - Does a page targeting this topic exist? If not, create it — give the engine a reason to name you.
138
186
  - Is it indexed? If not, submit it.
139
187
  - Is it structured for AI extraction? (FAQ schema, clear H2s, definition-style answers)
140
188
 
141
- ### Provider variance (cited on one, not others)
189
+ ### Provider variance (mentioned/cited on one, not others)
142
190
  Expected — each provider has independent knowledge. Focus on the ones that matter most for the client's audience. Don't over-optimize for one provider at the expense of others.
143
191
 
144
192
  ## The AEO Timeline Reality
@@ -103,24 +103,35 @@ Use `--probe` whenever you're testing on your own initiative — verifying a fix
103
103
 
104
104
  `snapshot` does not create a project or write to the DB. It generates category queries, runs providers, and produces a report for prospecting.
105
105
 
106
- ## Citation Data
106
+ ## Mention + Citation Data
107
+
108
+ Two independent signals per (query × provider): **mention** (`answerMentioned` — brand named in the answer text; the **primary** read) and **citation** (`cited`/`citedDomains` — domain in the grounding sources; **secondary**). Read mention first. Never compute one from the other; never coerce `answerMentioned` null → false (null = "not checked").
107
109
 
108
110
  ```bash
109
- cnry evidence <project> # per-query cited/not-cited + mentioned/not-mentioned
111
+ cnry evidence <project> # per-query [C/c][M/m] cell + Mentioned: X / Y / Cited: X / Y
110
112
  cnry evidence <project> --format json # JSON output
111
113
  cnry history <project> # audit trail
112
114
  cnry export <project> --include-results # export as YAML
113
- cnry backfill answer-visibility # recompute citationState from stored answers
114
- cnry backfill answer-visibility --dry-run # preview which snapshots would change
115
- cnry backfill answer-mentions # recompute answerMentioned from stored answers (honors brandAliases)
115
+ cnry backfill answer-mentions # recompute answerMentioned (primary) from stored answers (honors brandAliases)
116
116
  cnry backfill answer-mentions --dry-run
117
+ cnry backfill answer-visibility # recompute citationState (secondary) from stored answers
118
+ cnry backfill answer-visibility --dry-run # preview which snapshots would change
117
119
  cnry backfill insights <project> # recompute insights for completed runs
118
120
  cnry backfill insights <project> --since 2026-04-01 --dry-run
119
121
  ```
120
122
 
121
- Output uses a two-glyph cell per (query × provider): `[C/c][M/m]` — uppercase = present, lowercase = absent, `–` = no snapshot. Always print the legend before the table; never collapse the two signals into one cell.
123
+ Output uses a two-glyph cell per (query × provider): `[C/c][M/m]` — uppercase = present, lowercase = absent, `–` = no snapshot. **C/c = cited** (secondary), **M/m = mentioned** (primary). Always print the legend before the table; never collapse the two signals into one cell.
122
124
 
123
- Summary: `Cited: X / Y` and `Mentioned: X / Y` are reported independently — a query can be one, both, or neither.
125
+ ```
126
+ Legend: [C/c][M/m] C=cited c=not-cited M=mentioned m=not-mentioned –=no snapshot
127
+
128
+ [C][M] acme corp ny ← mentioned AND cited
129
+ [c][M] best crm for smb ← mentioned, not cited (mention win, citation gap)
130
+ [C][m] crm pricing ← cited, not mentioned (citation without share of voice)
131
+ [c][m] free crm tools ← neither
132
+ ```
133
+
134
+ Summary: `Mentioned: X / Y` (primary) and `Cited: X / Y` (secondary) are reported independently — a query can be one, both, or neither.
124
135
 
125
136
  ## Reports
126
137
 
@@ -144,8 +155,8 @@ Behavior to know when narrating numbers from the report:
144
155
 
145
156
  ```bash
146
157
  cnry analytics <project> # default analytics view
147
- cnry analytics <project> --feature metrics # citation rate trends
148
- cnry analytics <project> --feature gaps # brand gap analysis (cited/gap/uncited)
158
+ cnry analytics <project> --feature metrics # mention + citation rate trends (BrandMetricsDto: mentionTrend primary, trend secondary)
159
+ cnry analytics <project> --feature gaps # brand gap analysis — mention buckets (mentionedQueries[]/mentionGap[]/notMentioned[]) primary, cited buckets (cited[]/gap[]/uncited[]) secondary
149
160
  cnry analytics <project> --feature sources # source breakdown by category
150
161
  cnry analytics <project> --window 7d # time window: 7d, 30d, 90d, all
151
162
  ```
@@ -190,7 +201,7 @@ cnry insights <project> # list active insights (regressio
190
201
  cnry insights <project> --dismissed # include dismissed insights
191
202
  cnry insights <project> --format json # JSON output
192
203
  cnry insights dismiss <project> <id> # dismiss an insight
193
- cnry health <project> # latest citation health snapshot
204
+ cnry health <project> # latest citation health snapshot (citation-only — see known gap below)
194
205
  cnry health <project> --history # health trend over time
195
206
  cnry health <project> --history --limit 10 # limit history entries
196
207
  cnry health <project> --format json # JSON output
@@ -198,6 +209,8 @@ cnry backfill insights <project> # backfill insights for all comple
198
209
  cnry backfill insights <project> --from-run <id> --to-run <id> # backfill a range
199
210
  ```
200
211
 
212
+ > **Known gap (mention-first read):** `cnry health` is **citation-only** today — it has no mention dimension. For the primary mention-first read, use `cnry overview` and `cnry get <project> scores.mentionCoverage.value` / `cnry get <project> scores.mentionShare.value` until health is extended.
213
+
201
214
  ## Queries & Competitors
202
215
 
203
216
  ```bash
@@ -237,6 +250,8 @@ Available events: `citation.lost`, `citation.gained`, `run.completed`, `run.fail
237
250
 
238
251
  `insight.critical` and `insight.high` fire when the intelligence engine generates critical- or high-severity insights after a sweep completes.
239
252
 
253
+ > **No mention events yet.** Notification events cover the citation signal only — there are **no** `mention.lost` / `mention.gained` events today. For mention-first monitoring, read `scores.mentionCoverage` / `scores.mentionShare` via `cnry overview` (or the `insight.*` events, which can be driven by mention-side insights); do not wire automation to mention events that aren't emitted.
254
+
240
255
  ## Provider Settings & Quotas
241
256
 
242
257
  ```bash