@canonry/canonry 7.10.0 → 7.12.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 (35) hide show
  1. package/assets/agent-workspace/skills/aero/references/reporting.md +2 -0
  2. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +1 -1
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +30 -4
  4. package/assets/assets/{AuditHistoryPanel-BgcvPo6g.js → AuditHistoryPanel-Bpkuj-iF.js} +1 -1
  5. package/assets/assets/{BacklinksPage-DZ4tauAs.js → BacklinksPage-CbRIZhu5.js} +1 -1
  6. package/assets/assets/{HistoryPage-DWG52dz1.js → HistoryPage-Dfq1vK9k.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-DTx2iQLV.js → MeasurementPropertyPage-DcH0zYNN.js} +1 -1
  8. package/assets/assets/ProjectPage-enF4twWt.js +8 -0
  9. package/assets/assets/{RunsPage-B6MhRqxN.js → RunsPage-aOeJ60pX.js} +1 -1
  10. package/assets/assets/{SettingsPage-Bxv7OSHT.js → SettingsPage-nA0_ImoQ.js} +1 -1
  11. package/assets/assets/{SiteHealthSection-C5x7oiFL.js → SiteHealthSection-CUOt7jeo.js} +3 -3
  12. package/assets/assets/{TrafficPage-C5gyQopi.js → TrafficPage-C0fVYizx.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-Dv2ZRNvN.js → TrafficSourceDetailPage-LMhXbFlA.js} +1 -1
  14. package/assets/assets/{extract-error-message-C5pr51ph.js → extract-error-message-5aHy0fsK.js} +1 -1
  15. package/assets/assets/index-BJh8cX5E.js +86 -0
  16. package/assets/assets/index-BNeiohKS.css +1 -0
  17. package/assets/assets/{react-sigma_core.esm.min-P5bVaYly.js → react-sigma_core.esm.min-ldX35rMq.js} +1 -1
  18. package/assets/assets/{v2-overview-adapter-QtI4xO_4.js → v2-overview-adapter-CaO9vY-l.js} +1 -1
  19. package/assets/index.html +2 -2
  20. package/dist/{chunk-5ZBN3EEK.js → chunk-7I64KEGM.js} +2 -2
  21. package/dist/{chunk-66DVP4DN.js → chunk-AU7OUDWR.js} +5786 -4450
  22. package/dist/{chunk-VSZJVBVR.js → chunk-BTHEFJCI.js} +60 -8
  23. package/dist/{chunk-FVMWUT2R.js → chunk-DXI2FTSW.js} +706 -257
  24. package/dist/{chunk-HL3C6Z7T.js → chunk-EPSHIH63.js} +3 -3
  25. package/dist/{chunk-52PHEGHT.js → chunk-GQMSJEMZ.js} +3515 -2266
  26. package/dist/{chunk-IKXVLT4M.js → chunk-SM6ZZAPK.js} +93 -5
  27. package/dist/cli.js +177 -40
  28. package/dist/{demo-server-WZIB4JKJ.js → demo-server-WJUA4EIG.js} +4 -4
  29. package/dist/index.js +6 -6
  30. package/dist/{intelligence-service-KC62A4X5.js → intelligence-service-DJRH4Z3D.js} +2 -2
  31. package/dist/mcp.js +4 -4
  32. package/package.json +12 -12
  33. package/assets/assets/ProjectPage-CCf70zbI.js +0 -8
  34. package/assets/assets/index-BhXHm5nG.js +0 -86
  35. package/assets/assets/index-Rcbm8bK1.css +0 -1
@@ -29,6 +29,7 @@ import {
29
29
  calendarDateSchema,
30
30
  canonicalizeGtmAccountId,
31
31
  canonicalizeGtmResourceSelection,
32
+ competitorAliasBlockRequestSchema,
32
33
  competitorAliasesRequestSchema,
33
34
  competitorAppendRequestSchema,
34
35
  competitorBatchRequestSchema,
@@ -138,7 +139,7 @@ import {
138
139
  trafficSeriesGranularitySchema,
139
140
  visibilityCompareSelectionSchema,
140
141
  visibilityReportRequestSchema
141
- } from "./chunk-66DVP4DN.js";
142
+ } from "./chunk-AU7OUDWR.js";
142
143
 
143
144
  // src/cli-error.ts
144
145
  function isMachineFormat(format) {
@@ -523,6 +524,8 @@ var runsListInputSchema = z3.object({
523
524
  project: projectNameSchema,
524
525
  limit: z3.number().int().positive().max(500).optional(),
525
526
  kind: runListFilterQuerySchema.shape.kind.describe('Restrict to a single run kind (e.g. "answer-visibility"). Unknown values are rejected.'),
527
+ excludeKind: runListFilterQuerySchema.shape.excludeKind.describe('Exclude one run kind before applying the limit (e.g. "bing-inspect" omits single-URL inspections). Combines with kind and status.'),
528
+ excludeKinds: runListFilterQuerySchema.shape.excludeKinds.describe('Exclude multiple run kinds before applying the limit (e.g. ["bing-inspect", "traffic-sync"] keeps meaningful Activity jobs). Combines with excludeKind, kind, and status.'),
526
529
  status: runListFilterQuerySchema.shape.status.describe('Restrict to a single run status (e.g. "running" for in-flight work, "failed" to triage). Unknown values are rejected.')
527
530
  });
528
531
  var runGetInputSchema = z3.object({
@@ -909,9 +912,14 @@ var competitorsAddInputSchema = z3.object({
909
912
  project: projectNameSchema,
910
913
  request: competitorAppendRequestSchema
911
914
  });
915
+ var competitorDomainInputSchema = z3.string().trim().min(1).describe("Tracked competitor domain (any spelling; it resolves to the stored registrable domain).");
912
916
  var competitorAliasesInputSchema = competitorAliasesRequestSchema.safeExtend({
913
917
  project: projectNameSchema,
914
- domain: z3.string().trim().min(1).describe("Tracked competitor domain (any spelling; it resolves to the stored registrable domain).")
918
+ domain: competitorDomainInputSchema
919
+ });
920
+ var competitorAliasBlockInputSchema = competitorAliasBlockRequestSchema.safeExtend({
921
+ project: projectNameSchema,
922
+ domain: competitorDomainInputSchema
915
923
  });
916
924
  var latestSweepRunIdDescription = "A run id, or latest for the latest sweep (the run the measurement reads display). With queryClass branded or non-brand and neither runId nor window, this tool reads latest; pass window to pool every sweep in it.";
917
925
  var competitorLandscapeInputSchema = competitorLandscapeQuerySchema.safeExtend({
@@ -1637,13 +1645,13 @@ var canonryMcpTools = [
1637
1645
  defineTool({
1638
1646
  name: "canonry_runs_list",
1639
1647
  title: "List project runs",
1640
- description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications \u2014 filter by `trigger !== 'probe'` if you only want runs that feed project metrics. Narrow with `kind` and/or `status` (e.g. status='running' lists only in-flight work).",
1648
+ description: "List runs for a Canonry project. Includes both real runs (trigger='manual'/'scheduled'/'config-apply'/'backfill') AND probe runs (trigger='probe'). Probe runs are operator/agent test runs that don't influence dashboard, analytics, intelligence, or notifications \u2014 filter by `trigger !== 'probe'` if you only want runs that feed project metrics. Narrow with `kind` and/or `status` (e.g. status='running' lists only in-flight work). Use `excludeKind` or `excludeKinds` to remove kinds before applying the limit.",
1641
1649
  access: "read",
1642
1650
  tier: "monitoring",
1643
1651
  inputSchema: runsListInputSchema,
1644
1652
  annotations: readAnnotations(),
1645
1653
  openApiOperations: ["GET /api/v1/projects/{name}/runs"],
1646
- handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status)
1654
+ handler: (client, input) => client.listRuns(input.project, input.limit, input.kind, input.status, input.excludeKind, input.excludeKinds)
1647
1655
  }),
1648
1656
  defineTool({
1649
1657
  name: "canonry_runs_latest",
@@ -1957,7 +1965,7 @@ var canonryMcpTools = [
1957
1965
  defineTool({
1958
1966
  name: "canonry_competitors_list",
1959
1967
  title: "List competitors",
1960
- description: "List tracked competitors for a Canonry project, each with its operator-curated `aliases` (the names it goes by in answer text; `[]` means the domain label alone identifies it).",
1968
+ description: "List tracked competitors for a Canonry project, each with its operator-curated `aliases` (the names it goes by in answer text; `[]` means the domain label alone identifies it), its `autoAliases` (names detected automatically from the project's stored answers, each with its evidence) and its `blockedAliases` (names the operator blocked from auto-detection).",
1961
1969
  access: "read",
1962
1970
  tier: "setup",
1963
1971
  inputSchema: projectInputSchema,
@@ -2693,7 +2701,7 @@ var canonryMcpTools = [
2693
2701
  defineTool({
2694
2702
  name: "canonry_project_upsert",
2695
2703
  title: "Create or replace project",
2696
- description: "Create or replace a Canonry project. PUT semantics: fields not in the request are reset to their defaults. Provide the full intended project shape. Exceptions: an omitted providerDispatchModes (provider \u2192 sync|batch for scheduled sweeps) keeps the stored preference; send {} to clear it. An omitted qualifiedAliases (the aliases Simple sentiment treats as this brand's own names) keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it. Competitors are not part of this request, but a new identity (display name, aliases, domains) that claims a tracked competitor's curated alias drops that alias, and the drop is audited. An omitted siteAuditMaxPages (the Site Health page budget for scans that set none, 1 to 50,000) keeps the stored budget; send null for the full site.",
2704
+ description: "Create or replace a Canonry project. PUT semantics: fields not in the request are reset to their defaults. Provide the full intended project shape. Exceptions: an omitted providerDispatchModes (provider \u2192 sync|batch for scheduled sweeps) keeps the stored preference; send {} to clear it. An omitted qualifiedAliases (the aliases Simple sentiment treats as this brand's own names) keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it. Competitors are not part of this request, but a new identity (display name, aliases, domains) that claims a tracked competitor's curated alias drops that alias, and the drop is audited. An omitted siteAuditMaxPages (the Site Health page budget for scans that set none, 1 to 50,000) keeps the stored budget; send null for the full site. An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode: `off` (no unattended detection pass), `preview` (the default: detect and log, store nothing) or `apply` (store the detected names, which restates history).",
2697
2705
  access: "write",
2698
2706
  tier: "setup",
2699
2707
  inputSchema: projectUpsertInputSchema,
@@ -2704,7 +2712,7 @@ var canonryMcpTools = [
2704
2712
  defineTool({
2705
2713
  name: "canonry_apply_config",
2706
2714
  title: "Apply project config",
2707
- description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). For multi-document YAML, call this tool once per project document.",
2715
+ description: "Apply one Canonry config-as-code project document. Replaces the project to match the config; fields omitted from the spec are reset to defaults, with these exceptions: a spec with neither queries nor keywords leaves the tracked-query basket unchanged (to clear the basket, pass an explicit empty queries list); an omitted providerDispatchModes keeps the stored preference; an omitted qualifiedAliases keeps the stored list, minus names that no longer qualify (a removed alias, a spelling of the display name, or a competitor's name); send [] to clear it; and a competitor given as a plain domain keeps its stored curated aliases, while `{ domain, aliases }` sets them exactly (`[]` clears). A spec identity that claims a competitor's alias drops that alias (audited); a new competitor whose name overlaps another competitor's alias (one brand key contains the other) or that is the project's own site fails the apply. An omitted siteAuditMaxPages keeps the stored Site Health page budget (null means the full site). An omitted competitorAutoAliases keeps the stored answer-derived competitor alias mode (off, preview or apply). For multi-document YAML, call this tool once per project document.",
2708
2716
  access: "write",
2709
2717
  tier: "core",
2710
2718
  inputSchema: applyConfigInputSchema,
@@ -3273,7 +3281,7 @@ var canonryMcpTools = [
3273
3281
  defineTool({
3274
3282
  name: "canonry_competitors_aliases_set",
3275
3283
  title: "Set competitor aliases",
3276
- description: `Set one tracked competitor's operator-curated aliases exactly (\`[]\` clears): the brand names it goes by in answer text when they differ from its domain, e.g. "TuneSpoke" for spoketuneworks.example or a 3-letter brand the domain label floor drops. Every competitor mention matcher (mention share, competitor landscape, mention gaps, run and history signals) uses them on stored answers at read time. Rejected: aliases under 3 letters or digits, over 80 characters, more than 10, or whose brand key contains, or sits inside, one of the project's own names or hosts or a name another tracked competitor answers to (its aliases, domain label or written host), because answers may split or join the words: "Tune" cannot belong to one competitor while another answers to "Tune Spoke", "TuneSpoke" or tunespoke.example, and joined-word lookalikes ("Tune" and "Tuner") are refused too. A competitor an Advanced market pins (active revision, pending draft, or a superseded revision the project's runs were measured under) counts as another competitor. Idempotent; returns the competitor.`,
3284
+ description: 'Set one tracked competitor\'s operator-curated aliases exactly (`[]` clears): the brand names it goes by in answer text when they differ from its domain, e.g. "TuneSpoke" for spoketuneworks.example or a 3-letter brand the domain label floor drops. Every competitor mention matcher (mention share, competitor landscape, mention gaps, run and history signals) uses them on stored answers at read time. Rejected: aliases under 3 letters or digits, over 80 characters, more than 10, or whose brand key contains, or sits inside, one of the project\'s own names or hosts or a name another tracked competitor answers to (its aliases, domain label or written host), because answers may split or join the words: "Tune" cannot belong to one competitor while another answers to "Tune Spoke", "TuneSpoke" or tunespoke.example, and joined-word lookalikes ("Tune" and "Tuner") are refused too. A competitor an Advanced market pins (active revision, pending draft, or a superseded revision the project\'s runs were measured under) counts as another competitor. Names detected automatically from stored answers (`autoAliases`) are matched the same way; a curated alias always wins, so an auto name the new list overlaps is dropped. Idempotent; returns the competitor.',
3277
3285
  access: "write",
3278
3286
  tier: "setup",
3279
3287
  inputSchema: competitorAliasesInputSchema,
@@ -3281,6 +3289,50 @@ var canonryMcpTools = [
3281
3289
  openApiOperations: ["PUT /api/v1/projects/{name}/competitors/{domain}/aliases"],
3282
3290
  handler: (client, input) => client.setCompetitorAliases(input.project, input.domain, input.aliases)
3283
3291
  }),
3292
+ defineTool({
3293
+ name: "canonry_competitors_auto_aliases_detect",
3294
+ title: "Preview competitor auto-aliases",
3295
+ description: `Dry run of automatic competitor alias detection from the project's stored answers only (never a provider, never a competitor's website). Per competitor: the names the answers pair with its site (provider citations anchoring the name to a page on the domain, named links, \`Name (domain)\`), with evidence (direct pairs, sweeps, co-occurrences, answers naming it, precision = share of those that cite the site, lift = how much more often the site is cited when the name appears, answers writing it as a name; an answer names a candidate only where it writes it outside the competitor's longer names: domain label, curated aliases, longer stored names, and for a market-only competitor its plan label and aliases), and each name's status: added, kept, removed, review or rejected with a reason. A name is applied only if it passes the evidence bars, reads as a business name, not a place ("Larkfield, CO", "Oakvale County", "Metro Larkfield"), and visibly belongs to the domain: consecutive words of it spell the domain label; or a name of two or more words opens the label whole (at its start or after a lead word such as "my" or "get") and covers at least half of it; or two or more of its words sit back to back in the label from that opening and cover at least half of it, one of them 4+ letters and inside fewer than two tracked identity labels; or a name of two or more words is an in-order abbreviation that opens like the label ("FoamSeal" for foamandsealworks.example). One shared word is never enough unless it is the whole label. New names fill the cap of 10 strongest evidence first, and a name the competitor's own label, curated aliases, kept names or own active or draft market pin already cover is not learned. Review names (no such tie, or a 3-letter name) are never auto-applied; they are checked against the project's names and hosts, other competitors' domain labels, hosts and curated aliases, market pins of another domain, blocks and the competitor's own names, but not against other competitors' auto-detected names. Verify one refers to that competitor before adding it as a curated alias. A stored name is removed only when blocked, claimed by identity (its own curated names, the project's names or hosts, another competitor's domain label, host, curated alias or earlier stored auto name, a market pin of another domain), replaced by an accepted shorter name, or contradicted: named in 3+ answers with precision under 5%, lift under 1.5 or name casing under half; another tracked competitor pairing it in at least 2 answers and at least twice as often; or no tie to the domain label left. Writes nothing. The local server queues the same pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins, run by the project's competitorAutoAliases mode: \`apply\` stores its result, \`preview\` (the default) only logs it, \`off\` skips it.`,
3296
+ access: "read",
3297
+ tier: "setup",
3298
+ inputSchema: projectInputSchema,
3299
+ annotations: readAnnotations(),
3300
+ openApiOperations: ["GET /api/v1/projects/{name}/competitor-auto-aliases"],
3301
+ handler: (client, input) => client.previewCompetitorAutoAliases(input.project)
3302
+ }),
3303
+ defineTool({
3304
+ name: "canonry_competitors_auto_aliases_apply",
3305
+ title: "Apply competitor auto-aliases",
3306
+ description: "Run automatic competitor alias detection now from the project's stored answers and store the result, whatever the project's competitorAutoAliases mode (a one-off apply; a project in `apply` mode also gets this pass after every completed or partial sweep, a competitor add, an unblock and a market pin write that changes the pins). Stored names restate history at read time: every period's competitor counts change, and so does share of voice for a tracked competitor; competitorIdentityChangedAt on the landscape, project-frame visibility-compare and analytics metrics marks when. Idempotent: unchanged answers write nothing. Curated aliases and blocked names always win. A change is audited as the system pass plus competitors.auto-aliases-apply-requested naming who asked. Not available to the built-in Aero agent. Returns what was stored, per competitor, with evidence.",
3307
+ access: "write",
3308
+ tier: "setup",
3309
+ inputSchema: projectInputSchema,
3310
+ annotations: writeAnnotations({ idempotentHint: true }),
3311
+ openApiOperations: ["POST /api/v1/projects/{name}/competitor-auto-aliases"],
3312
+ handler: (client, input) => client.applyCompetitorAutoAliases(input.project)
3313
+ }),
3314
+ defineTool({
3315
+ name: "canonry_competitors_aliases_block",
3316
+ title: "Block competitor auto-aliases",
3317
+ description: "Block names from automatic, answer-derived alias detection for one competitor, by domain: a tracked competitor, else a competitor the active Advanced plan pins without tracking it, else a domain with stored market competitor names and no active pin (names learned for a pin a later revision dropped, or the blocks a removed competitor left). A blocked name is never auto-applied again until unblocked, and a stored auto name among them is removed now. Blocks survive removing and re-adding the competitor. Names compare by brand key (case, spacing and punctuation variants are one name). A curated alias cannot be blocked; remove it with canonry_competitors_aliases_set. A name the measurement plan's own pin of that competitor carries (active revision or pending draft) cannot be blocked either, because the pin keeps counting it; change the pin's names in a measurement draft. Idempotent; returns the competitor.",
3318
+ access: "write",
3319
+ tier: "setup",
3320
+ inputSchema: competitorAliasBlockInputSchema,
3321
+ annotations: writeAnnotations({ idempotentHint: true }),
3322
+ openApiOperations: ["POST /api/v1/projects/{name}/competitors/{domain}/aliases/block"],
3323
+ handler: (client, input) => client.blockCompetitorAliases(input.project, input.domain, input.aliases)
3324
+ }),
3325
+ defineTool({
3326
+ name: "canonry_competitors_aliases_unblock",
3327
+ title: "Unblock competitor auto-aliases",
3328
+ description: "Release blocked names back to automatic, answer-derived alias detection for one competitor, by domain: a tracked competitor, else a competitor the active Advanced plan pins without tracking it, else a domain with stored market competitor names and no active pin (names learned for a pin a later revision dropped, or the blocks a removed competitor left, which this releases). The unblock stores nothing new; a detection pass is requested and, for a project in `apply` mode, stores a name only if the stored answers still support it (in `preview` it only logs, in `off` it does not run; canonry_competitors_auto_aliases_apply stores now). A learned name still stored for a market-only competitor counts again at once. Idempotent; returns the competitor.",
3329
+ access: "write",
3330
+ tier: "setup",
3331
+ inputSchema: competitorAliasBlockInputSchema,
3332
+ annotations: writeAnnotations({ idempotentHint: true }),
3333
+ openApiOperations: ["POST /api/v1/projects/{name}/competitors/{domain}/aliases/unblock"],
3334
+ handler: (client, input) => client.unblockCompetitorAliases(input.project, input.domain, input.aliases)
3335
+ }),
3284
3336
  defineTool({
3285
3337
  name: "canonry_competitors_remove",
3286
3338
  title: "Remove competitors",