@canonry/canonry 7.17.1 → 7.18.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 (36) hide show
  1. package/assets/agent-workspace/skills/aero/references/portfolio-analysis.md +8 -6
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +1 -1
  3. package/assets/assets/{AuditHistoryPanel-CzjskfMX.js → AuditHistoryPanel-CgKpjgpq.js} +1 -1
  4. package/assets/assets/BacklinksPage-BBqbRSeG.js +1 -0
  5. package/assets/assets/Hint-DICI5Jq9.js +1 -0
  6. package/assets/assets/{HistoryPage-BZgVoYGm.js → HistoryPage-D8nQ8E8_.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-EBI5sn-D.js → MeasurementPropertyPage-CQ8lLoeA.js} +1 -1
  8. package/assets/assets/{ProjectPage-lGGjM_qj.js → ProjectPage-CP4fvluh.js} +6 -6
  9. package/assets/assets/{RunsPage-CuHi8241.js → RunsPage-D0qkTwas.js} +1 -1
  10. package/assets/assets/{SettingsPage-D0fgAoVu.js → SettingsPage-DaqR1wKC.js} +1 -1
  11. package/assets/assets/SiteHealthSection-dGXxZ8IR.js +4 -0
  12. package/assets/assets/{TrafficPage-DD65RqeR.js → TrafficPage-DodOmnVv.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-CFVCj13J.js → TrafficSourceDetailPage-C7b-BcKF.js} +1 -1
  14. package/assets/assets/{extract-error-message-D118msoE.js → extract-error-message-BYvzTsML.js} +1 -1
  15. package/assets/assets/index-BVzozur0.js +86 -0
  16. package/assets/assets/{react-sigma_core.esm.min-DdlHLMEz.js → react-sigma_core.esm.min-DXcq1O0r.js} +1 -1
  17. package/assets/assets/{v2-overview-adapter-CoCb2aB0.js → v2-overview-adapter-1MHnrdnr.js} +1 -1
  18. package/assets/assets/{vendor-lucide-N6vOpZmh.js → vendor-lucide-Y6jANGfG.js} +1 -1
  19. package/assets/index.html +2 -2
  20. package/dist/{chunk-ORA5R7QM.js → chunk-5M2RY5WU.js} +132 -104
  21. package/dist/{chunk-ZQ7C6IFA.js → chunk-COQOQYRZ.js} +749 -614
  22. package/dist/{chunk-FK7AWV57.js → chunk-EAAM47H6.js} +24 -9
  23. package/dist/{chunk-PLS4EM2Y.js → chunk-JMC7CEJB.js} +4 -4
  24. package/dist/{chunk-OPJCFDNR.js → chunk-JUOFNJLV.js} +3 -3
  25. package/dist/{chunk-C6GWKYGE.js → chunk-U7D7LNVJ.js} +5 -4
  26. package/dist/{chunk-MHB23E3N.js → chunk-X2S7D3MN.js} +123 -82
  27. package/dist/cli.js +30 -22
  28. package/dist/{demo-server-WQDHQG6P.js → demo-server-XWRIXME5.js} +6 -5
  29. package/dist/index.d.ts +7 -5
  30. package/dist/index.js +6 -6
  31. package/dist/{intelligence-service-JWZRZ6JZ.js → intelligence-service-332S7D7Y.js} +2 -2
  32. package/dist/mcp.js +4 -4
  33. package/package.json +12 -12
  34. package/assets/assets/BacklinksPage-ToENGBdp.js +0 -1
  35. package/assets/assets/SiteHealthSection-DhLxldgs.js +0 -4
  36. package/assets/assets/index-DxFd1t4G.js +0 -86
@@ -6,6 +6,7 @@ import {
6
6
  GA_SEARCH_LANDING_MAX_LIMIT,
7
7
  GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX,
8
8
  LATEST_RUN_ID,
9
+ MEASUREMENT_DEFAULT_QUERY_CLASS,
9
10
  PROVIDER_ACCOUNT_FAILURE_STREAK,
10
11
  PROVIDER_ACCOUNT_RETRY_HOURS,
11
12
  RESEARCH_RUN_SCOPE,
@@ -141,7 +142,7 @@ import {
141
142
  trafficSeriesGranularitySchema,
142
143
  visibilityCompareSelectionSchema,
143
144
  visibilityReportRequestSchema
144
- } from "./chunk-MHB23E3N.js";
145
+ } from "./chunk-X2S7D3MN.js";
145
146
 
146
147
  // src/cli-error.ts
147
148
  function isMachineFormat(format) {
@@ -390,7 +391,8 @@ var runTriggerInputSchema = z3.object({
390
391
  });
391
392
  var measurementPlanVersionInputSchema = z3.object({ project: projectNameSchema, revision: z3.number().int().positive() });
392
393
  var measurementReportInputSchema = measurementPlanVersionInputSchema.extend({
393
- runId: runIdSchema.optional().describe("Exact eligible full measurement run to reconstruct. Omit for the latest run in the revision.")
394
+ runId: runIdSchema.optional().describe("Exact eligible full measurement run to reconstruct. Omit for the latest run in the revision."),
395
+ queryClass: measurementQueryClassFilterSchema.optional().describe("Omit for non-brand on a schema v2 revision; read branded as a separate call. all pools both classes. A schema v1 revision records no class: omit it there.")
394
396
  });
395
397
  var measurementPlanPreviewInputSchema = z3.object({ project: projectNameSchema, plan: measurementPlanAuthoringSchema });
396
398
  var measurementPlanPublishInputSchema = measurementPlanPublishRequestSchema.extend({ project: projectNameSchema });
@@ -399,10 +401,11 @@ var measurementDiscoveryInputSchema = measurementDiscoveryRequestSchema.extend({
399
401
  var idempotencyKeyInputSchema = z3.string().trim().min(1).describe("A fresh request key. Reuse it only when retrying the identical request.");
400
402
  var measurementOverviewInputSchema = z3.object({
401
403
  project: projectNameSchema,
402
- scope: measurementOverviewQuerySchema.shape.scope.describe("Read all Properties, one reporting group, or one Property."),
404
+ scope: measurementOverviewQuerySchema.shape.scope.describe("Read all Properties, one group (every query of its Properties), one market (only the market's own queries, as the dashboard's market view), or one Property. A group and a market can share a name and still differ; for a market, use market scope."),
403
405
  groupKey: measurementOverviewQuerySchema.shape.groupKey.describe("Group stable key. Required only for group scope."),
406
+ marketKey: measurementOverviewQuerySchema.shape.marketKey.describe("Market stable key. Required only for market scope."),
404
407
  targetKey: measurementOverviewQuerySchema.shape.targetKey.describe("Property stable key. Required only for property scope."),
405
- queryClass: measurementOverviewQuerySchema.shape.queryClass.describe("Select non-brand for acquisition performance or branded for brand awareness. Omitted means all classes combined; always name the class in the report."),
408
+ queryClass: measurementOverviewQuerySchema.shape.queryClass.describe("Omit for non-brand, the acquisition signal. Read branded (brand recall) as a separate call. all pools both classes into one rate, so never report it as one class."),
406
409
  provider: measurementOverviewQuerySchema.shape.provider,
407
410
  location: measurementOverviewQuerySchema.shape.location,
408
411
  from: measurementOverviewQuerySchema.shape.from,
@@ -420,14 +423,20 @@ var measurementOverviewInputSchema = z3.object({
420
423
  if (input.scope === "property" && !input.targetKey) {
421
424
  context.addIssue({ code: "custom", path: ["targetKey"], message: "Property scope requires targetKey." });
422
425
  }
426
+ if (input.scope === "market" && !input.marketKey) {
427
+ context.addIssue({ code: "custom", path: ["marketKey"], message: "Market scope requires marketKey." });
428
+ }
423
429
  if (input.scope !== "group" && input.groupKey) {
424
430
  context.addIssue({ code: "custom", path: ["groupKey"], message: `${input.scope} scope does not accept groupKey.` });
425
431
  }
432
+ if (input.scope !== "market" && input.marketKey) {
433
+ context.addIssue({ code: "custom", path: ["marketKey"], message: `${input.scope} scope does not accept marketKey.` });
434
+ }
426
435
  if (input.scope !== "property" && input.targetKey) {
427
436
  context.addIssue({ code: "custom", path: ["targetKey"], message: `${input.scope} scope does not accept targetKey.` });
428
437
  }
429
438
  });
430
- var AGENT_DEFAULT_QUERY_CLASS = "non-brand";
439
+ var AGENT_DEFAULT_QUERY_CLASS = MEASUREMENT_DEFAULT_QUERY_CLASS;
431
440
  var propertyQueryClassInputSchema = measurementQueryClassFilterSchema.optional().describe("Omit for non-brand. branded reads brand recall; all pools both classes, so name the class you report.");
432
441
  function agentQueryClass(queryClass) {
433
442
  return queryClass ?? AGENT_DEFAULT_QUERY_CLASS;
@@ -2911,7 +2920,7 @@ var canonryMcpTools = [
2911
2920
  defineTool({
2912
2921
  name: "canonry_measurement_overview",
2913
2922
  title: "Get Advanced Measurement overview",
2914
- description: "Compact pages are byte-bounded whole rows by default; use nextCursor with unchanged filters. For best/worst Property mention rankings, prefer canonry_measurement_portfolio_summary and its mentionRanking. An unavailable aggregate does not invalidate available Property metrics. Return stored, revision-pinned Advanced Measurement metrics and a bounded page of Property rows for all Properties, one reporting group, or one Property. Filter by query class, provider, location, date window, run, or Property search; search filters rows without changing metric denominators. On a schema-v2 plan each Property row carries its metro (and otherMetros when it is in several). It ranks one run snapshot only and never infers a trend or compares across revisions. Choose label-asc (default), label-desc, citationCoverage-asc/desc, or mentionCoverage-asc/desc. For a coverage sort, unavailable rows form the first bucket in either direction; available rows then follow the requested numeric direction. The cursor is sort-aware, pins pagination to the active revision, displayed run, evidence snapshot, and filters even if a newer run completes, and must be reused unchanged with the same sort and filters. Legacy label cursors work only when sort is omitted, while any explicit sort needs a new sort-bound cursor. It never starts provider work or incurs provider cost; page size is at most 100, and it refuses invalid scope keys, cursor combinations, appended evidence, or a run pinned to another revision.",
2923
+ description: "Compact pages are byte-bounded whole rows by default; use nextCursor with unchanged filters. For best/worst Property mention rankings, prefer canonry_measurement_portfolio_summary and its mentionRanking. An unavailable aggregate does not invalidate available Property metrics. Return stored, revision-pinned Advanced Measurement metrics and a bounded page of Property rows for all Properties, one group, one market, or one Property. Defaults to non-brand queries: read branded as a separate call, state the returned queryClass, and never report queryClass all (both classes pooled) as one class. A group is every query of its Properties; a market is only its own queries, the dashboard's market population. Use market scope for a market's figures, and quote the returned scope kind and label: a group figure is never a market's figure. Filter by query class, provider, location, date window, run, or Property search; search filters rows without changing metric denominators. On a schema-v2 plan each Property row carries its metro (and otherMetros when it is in several). It ranks one run snapshot only and never infers a trend or compares across revisions. Choose label-asc (default), label-desc, citationCoverage-asc/desc, or mentionCoverage-asc/desc. For a coverage sort, unavailable rows form the first bucket in either direction; available rows then follow the requested numeric direction. The cursor is sort-aware, pins pagination to the active revision, displayed run, evidence snapshot, and filters even if a newer run completes, and must be reused unchanged with the same sort and filters. Legacy label cursors work only when sort is omitted, while any explicit sort needs a new sort-bound cursor. It never starts provider work or incurs provider cost; page size is at most 100, and it refuses invalid scope keys, cursor combinations, appended evidence, or a run pinned to another revision.",
2915
2924
  access: "read",
2916
2925
  tier: "setup",
2917
2926
  inputSchema: measurementOverviewInputSchema,
@@ -2919,7 +2928,11 @@ var canonryMcpTools = [
2919
2928
  openApiOperations: ["GET /api/v1/projects/{name}/measurement-overview"],
2920
2929
  handler: (client, input) => {
2921
2930
  const { project, ...query } = input;
2922
- return client.getMeasurementOverview(project, { ...query, compact: query.compact ?? true });
2931
+ return client.getMeasurementOverview(project, {
2932
+ ...query,
2933
+ queryClass: agentQueryClass(query.queryClass),
2934
+ compact: query.compact ?? true
2935
+ });
2923
2936
  }
2924
2937
  }),
2925
2938
  defineTool({
@@ -3193,13 +3206,15 @@ var canonryMcpTools = [
3193
3206
  defineTool({
3194
3207
  name: "canonry_measurement_report",
3195
3208
  title: "Get measurement report",
3196
- description: "Get a revision-pinned Target and group measurement report from stored runs. Optionally pin the evidence to an exact eligible full run. Never starts live provider work.",
3209
+ description: "Get a revision-pinned Target and group measurement report from stored runs. Optionally pin the evidence to an exact eligible full run. On a schema v2 revision every rate is taken over non-brand queries unless queryClass names another class, and the response echoes queryClass; read branded as a separate call, and treat all as pooled. A schema v1 revision records no class and echoes queryClass null. Never starts live provider work.",
3197
3210
  access: "read",
3198
3211
  tier: "setup",
3199
3212
  inputSchema: measurementReportInputSchema,
3200
3213
  annotations: readAnnotations(),
3201
3214
  openApiOperations: ["GET /api/v1/projects/{name}/measurement-report"],
3202
- handler: (client, input) => client.getMeasurementReport(input.project, input.revision, input.runId)
3215
+ // The class is sent only when named: the server serves non-brand on a v2
3216
+ // revision and every answer on a v1 revision, which refuses a named class.
3217
+ handler: (client, input) => client.getMeasurementReport(input.project, input.revision, input.runId, input.queryClass)
3203
3218
  }),
3204
3219
  defineTool({
3205
3220
  name: "canonry_run_trigger",
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-FK7AWV57.js";
8
+ } from "./chunk-EAAM47H6.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -50,7 +50,7 @@ import {
50
50
  skillsClientSchema,
51
51
  upgradeCaveatFor,
52
52
  upgradeCommandFor
53
- } from "./chunk-MHB23E3N.js";
53
+ } from "./chunk-X2S7D3MN.js";
54
54
 
55
55
  // src/config.ts
56
56
  import fs from "fs";
@@ -7027,12 +7027,12 @@ var ApiClient = class {
7027
7027
  })
7028
7028
  );
7029
7029
  }
7030
- async getMeasurementReport(project, revision, runId) {
7030
+ async getMeasurementReport(project, revision, runId, queryClass) {
7031
7031
  return this.invoke(
7032
7032
  () => getApiV1ProjectsByNameMeasurementReport({
7033
7033
  client: this.heyClient,
7034
7034
  path: { name: project },
7035
- query: { revision, runId }
7035
+ query: { revision, runId, ...queryClass === void 0 ? {} : { queryClass } }
7036
7036
  })
7037
7037
  );
7038
7038
  }
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-PLS4EM2Y.js";
7
+ } from "./chunk-JMC7CEJB.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
- } from "./chunk-FK7AWV57.js";
10
+ } from "./chunk-EAAM47H6.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-MHB23E3N.js";
14
+ } from "./chunk-X2S7D3MN.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";
@@ -5,16 +5,17 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-ZQ7C6IFA.js";
8
+ } from "./chunk-COQOQYRZ.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
12
12
  SiteAuditFactorStatuses,
13
13
  TEMPLATE_LINK_RATIO_THRESHOLD,
14
+ compareText,
14
15
  factorStatusFromDistribution,
15
16
  factorStatusFromScore,
16
17
  roundPreservingTotal
17
- } from "./chunk-MHB23E3N.js";
18
+ } from "./chunk-X2S7D3MN.js";
18
19
 
19
20
  // src/site-audit-factors.ts
20
21
  function recordedSharePct(factor) {
@@ -354,7 +355,7 @@ function siteCrawlGraphComponents(nodeKeys, edges) {
354
355
  if (group) group.push(key);
355
356
  else members.set(root, [key]);
356
357
  }
357
- return [...members.values()].sort((left, right) => right.length - left.length || (left[0] < right[0] ? -1 : left[0] > right[0] ? 1 : 0));
358
+ return [...members.values()].sort((left, right) => right.length - left.length || compareText(left[0], right[0]));
358
359
  }
359
360
  function describeComponent(nodeKeys, byKey) {
360
361
  let sumX = 0;
@@ -383,7 +384,7 @@ function packSiteCrawlGraphComponents(positions, edges, nodeSpacing) {
383
384
  const described = components.map((nodeKeys) => describeComponent(nodeKeys, byKey));
384
385
  const [anchor, ...rest] = described;
385
386
  const spacing = Math.max(nodeSpacing, Number.EPSILON) * COMPONENT_PACKING_SPACING_FACTOR;
386
- const ordered = [...rest].sort((left, right) => right.radius - left.radius || (left.nodeKeys[0] < right.nodeKeys[0] ? -1 : left.nodeKeys[0] > right.nodeKeys[0] ? 1 : 0));
387
+ const ordered = [...rest].sort((left, right) => right.radius - left.radius || compareText(left.nodeKeys[0], right.nodeKeys[0]));
387
388
  const moved = /* @__PURE__ */ new Map();
388
389
  let ringRadius = anchor.radius + spacing;
389
390
  let ringPitch = 0;