@canonry/canonry 4.145.0 → 4.146.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/assets/{AuditHistoryPanel-CV9g5mLR.js → AuditHistoryPanel-IDsSUFI3.js} +1 -1
  2. package/assets/assets/{BacklinksPage-RTcYKA5I.js → BacklinksPage-BswN-pyj.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-BMR0Dqnf.js → ChartPrimitives-CIe-R58_.js} +1 -1
  4. package/assets/assets/{HistoryPage-DAN9QO6x.js → HistoryPage-B18Jpq8c.js} +1 -1
  5. package/assets/assets/MeasurementPropertyPage-CvmQeoo7.js +1 -0
  6. package/assets/assets/ProjectPage-BE1MUAB5.js +11 -0
  7. package/assets/assets/{RunRow-WDCIS9MJ.js → RunRow-3ZwTR4Bv.js} +1 -1
  8. package/assets/assets/{RunsPage-D3Zxd6oc.js → RunsPage-BCAJulR1.js} +1 -1
  9. package/assets/assets/{SettingsPage-DcCFVeA7.js → SettingsPage-BT2_l0Do.js} +1 -1
  10. package/assets/assets/{TrafficPage-D0tPBu5O.js → TrafficPage-Cux8rj5G.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-CtyEE9eJ.js → TrafficSourceDetailPage-DI1Ad8KS.js} +1 -1
  12. package/assets/assets/{arrow-left-hBxXIGS1.js → arrow-left-BMSx9HQB.js} +1 -1
  13. package/assets/assets/extract-error-message-B-9FdQh8.js +1 -0
  14. package/assets/assets/index-C6E5hp28.css +1 -0
  15. package/assets/assets/index-kOXUzdqD.js +213 -0
  16. package/assets/assets/{trash-2-DP0ukgbl.js → trash-2-CyoJtRAr.js} +1 -1
  17. package/assets/assets/v2-overview-adapter-owDeFdUc.js +1 -0
  18. package/assets/assets/{vendor-markdown-6dwjPOKK.js → vendor-markdown-CpDJch4G.js} +1 -1
  19. package/assets/assets/{vendor-radix-CQ77EO2y.js → vendor-radix-DnzzbllM.js} +1 -1
  20. package/assets/assets/{vendor-recharts-DSxTZhaH.js → vendor-recharts-33ACLxsD.js} +1 -1
  21. package/assets/assets/vendor-tanstack-BjS7iY3g.js +1 -0
  22. package/assets/index.html +6 -6
  23. package/dist/{chunk-EFBTZ6ZT.js → chunk-B5H55ZMA.js} +87 -14
  24. package/dist/{chunk-GTBCGJNT.js → chunk-ED7C5TWT.js} +1560 -997
  25. package/dist/{chunk-MBLATP5L.js → chunk-UQOTEIA6.js} +110 -8
  26. package/dist/{chunk-XNAJXSZ2.js → chunk-Z7B6BRPP.js} +4 -4
  27. package/dist/cli.js +156 -4
  28. package/dist/index.js +4 -4
  29. package/dist/{intelligence-service-DVMEVHAG.js → intelligence-service-M5UNHF7X.js} +2 -2
  30. package/dist/mcp.js +2 -2
  31. package/package.json +11 -11
  32. package/assets/assets/ProjectPage-aFV2nddp.js +0 -9
  33. package/assets/assets/extract-error-message-DRu89RHb.js +0 -1
  34. package/assets/assets/index-ANFzZ3nU.css +0 -1
  35. package/assets/assets/index-DSOfEiTH.js +0 -213
  36. package/assets/assets/vendor-tanstack-Be8JdV5M.js +0 -1
@@ -28,6 +28,7 @@ import {
28
28
  keywordGenerateRequestSchema,
29
29
  measurementDiscoveryRequestSchema,
30
30
  measurementDraftApplyAssignmentsRequestSchema,
31
+ measurementDraftApplyPairedAssignmentsRequestSchema,
31
32
  measurementDraftApplySitemapSelectionRequestSchema,
32
33
  measurementDraftClassifyAssignmentsRequestSchema,
33
34
  measurementDraftClearAssignmentsRequestSchema,
@@ -49,6 +50,7 @@ import {
49
50
  measurementPlanAuthoringSchema,
50
51
  measurementPlanDeactivateRequestSchema,
51
52
  measurementPlanPublishRequestSchema,
53
+ measurementPropertyEvidenceQuerySchema,
52
54
  measurementQuerySetUpsertRequestSchema,
53
55
  measurementQueryTemplateApplyRequestSchema,
54
56
  measurementQueryTemplateUpsertRequestSchema,
@@ -69,7 +71,7 @@ import {
69
71
  trafficConnectWordpressRequestSchema,
70
72
  trafficEventKindSchema,
71
73
  trafficSeriesGranularitySchema
72
- } from "./chunk-EFBTZ6ZT.js";
74
+ } from "./chunk-B5H55ZMA.js";
73
75
 
74
76
  // src/config.ts
75
77
  import fs from "fs";
@@ -1498,6 +1500,22 @@ var postApiV1ProjectsByNameMeasurementPlanDraftActionsApplyAssignments = (option
1498
1500
  }
1499
1501
  });
1500
1502
  };
1503
+ var postApiV1ProjectsByNameMeasurementPlanDraftActionsApplyPairedAssignments = (options) => {
1504
+ return (options.client ?? client).post({
1505
+ security: [
1506
+ {
1507
+ scheme: "bearer",
1508
+ type: "http"
1509
+ }
1510
+ ],
1511
+ url: "/api/v1/projects/{name}/measurement-plan/draft/actions/apply-paired-assignments",
1512
+ ...options,
1513
+ headers: {
1514
+ "Content-Type": "application/json",
1515
+ ...options.headers
1516
+ }
1517
+ });
1518
+ };
1501
1519
  var postApiV1ProjectsByNameMeasurementPlanDraftActionsRemoveAssignment = (options) => {
1502
1520
  return (options.client ?? client).post({
1503
1521
  security: [
@@ -1690,6 +1708,18 @@ var getApiV1ProjectsByNameMeasurementOverview = (options) => {
1690
1708
  ...options
1691
1709
  });
1692
1710
  };
1711
+ var getApiV1ProjectsByNameMeasurementPropertyEvidence = (options) => {
1712
+ return (options.client ?? client).get({
1713
+ security: [
1714
+ {
1715
+ scheme: "bearer",
1716
+ type: "http"
1717
+ }
1718
+ ],
1719
+ url: "/api/v1/projects/{name}/measurement-property-evidence",
1720
+ ...options
1721
+ });
1722
+ };
1693
1723
  var getApiV1ProjectsByNameMeasurementQuerySets = (options) => {
1694
1724
  return (options.client ?? client).get({
1695
1725
  security: [
@@ -5320,12 +5350,12 @@ var ApiClient = class {
5320
5350
  })
5321
5351
  );
5322
5352
  }
5323
- async getMeasurementReport(project, revision) {
5353
+ async getMeasurementReport(project, revision, runId) {
5324
5354
  return this.invoke(
5325
5355
  () => getApiV1ProjectsByNameMeasurementReport({
5326
5356
  client: this.heyClient,
5327
5357
  path: { name: project },
5328
- query: { revision }
5358
+ query: { revision, runId }
5329
5359
  })
5330
5360
  );
5331
5361
  }
@@ -5344,6 +5374,15 @@ var ApiClient = class {
5344
5374
  })
5345
5375
  );
5346
5376
  }
5377
+ async getMeasurementPropertyEvidence(project, query) {
5378
+ return this.invoke(
5379
+ () => getApiV1ProjectsByNameMeasurementPropertyEvidence({
5380
+ client: this.heyClient,
5381
+ path: { name: project },
5382
+ query
5383
+ })
5384
+ );
5385
+ }
5347
5386
  async getMeasurementPlanDraft(project) {
5348
5387
  return this.invoke(
5349
5388
  () => getApiV1ProjectsByNameMeasurementPlanDraft({ client: this.heyClient, path: { name: project } })
@@ -5467,6 +5506,16 @@ var ApiClient = class {
5467
5506
  })
5468
5507
  );
5469
5508
  }
5509
+ async applyPairedMeasurementDraftAssignments(project, request, idempotencyKey, etag) {
5510
+ return this.invoke(
5511
+ () => postApiV1ProjectsByNameMeasurementPlanDraftActionsApplyPairedAssignments({
5512
+ client: this.heyClient,
5513
+ path: { name: project },
5514
+ body: request,
5515
+ headers: this.measurementDraftMutationHeaders(idempotencyKey, etag)
5516
+ })
5517
+ );
5518
+ }
5470
5519
  async removeMeasurementDraftAssignment(project, request, idempotencyKey, etag) {
5471
5520
  return this.invoke(
5472
5521
  () => postApiV1ProjectsByNameMeasurementPlanDraftActionsRemoveAssignment({
@@ -7209,6 +7258,9 @@ var runTriggerInputSchema = z2.object({
7209
7258
  request: runTriggerRequestSchema.optional()
7210
7259
  });
7211
7260
  var measurementPlanVersionInputSchema = z2.object({ project: projectNameSchema, revision: z2.number().int().positive() });
7261
+ var measurementReportInputSchema = measurementPlanVersionInputSchema.extend({
7262
+ runId: runIdSchema.optional().describe("Exact eligible full measurement run to reconstruct. Omit for the latest run in the revision.")
7263
+ });
7212
7264
  var measurementPlanPreviewInputSchema = z2.object({ project: projectNameSchema, plan: measurementPlanAuthoringSchema });
7213
7265
  var measurementPlanPublishInputSchema = measurementPlanPublishRequestSchema.extend({ project: projectNameSchema });
7214
7266
  var measurementPlanRetireInputSchema = z2.object({ project: projectNameSchema, stableKey: z2.string().min(1) });
@@ -7217,7 +7269,39 @@ var idempotencyKeyInputSchema = z2.string().trim().min(1).describe("A fresh requ
7217
7269
  var measurementDraftEtagInputSchema = z2.string().trim().min(1).optional().describe(
7218
7270
  "Current draft ETag from canonry_measurement_draft_get. The API requires it for draft edits, publish, and discard; omit it only to receive the API\u2019s actionable 428 response."
7219
7271
  );
7220
- var measurementOverviewInputSchema = measurementOverviewQuerySchema.extend({ project: projectNameSchema });
7272
+ var measurementOverviewInputSchema = z2.object({
7273
+ project: projectNameSchema,
7274
+ scope: measurementOverviewQuerySchema.shape.scope.describe("Read all Properties, one reporting group, or one Property."),
7275
+ groupKey: measurementOverviewQuerySchema.shape.groupKey.describe("Group stable key. Required only for group scope."),
7276
+ targetKey: measurementOverviewQuerySchema.shape.targetKey.describe("Property stable key. Required only for property scope."),
7277
+ queryClass: measurementOverviewQuerySchema.shape.queryClass,
7278
+ provider: measurementOverviewQuerySchema.shape.provider,
7279
+ location: measurementOverviewQuerySchema.shape.location,
7280
+ from: measurementOverviewQuerySchema.shape.from,
7281
+ to: measurementOverviewQuerySchema.shape.to,
7282
+ runId: measurementOverviewQuerySchema.shape.runId,
7283
+ search: measurementOverviewQuerySchema.shape.search,
7284
+ sort: measurementOverviewQuerySchema.shape.sort,
7285
+ cursor: measurementOverviewQuerySchema.shape.cursor,
7286
+ limit: measurementOverviewQuerySchema.shape.limit
7287
+ }).strict().superRefine((input, context) => {
7288
+ if (input.scope === "group" && !input.groupKey) {
7289
+ context.addIssue({ code: "custom", path: ["groupKey"], message: "Group scope requires groupKey." });
7290
+ }
7291
+ if (input.scope === "property" && !input.targetKey) {
7292
+ context.addIssue({ code: "custom", path: ["targetKey"], message: "Property scope requires targetKey." });
7293
+ }
7294
+ if (input.scope !== "group" && input.groupKey) {
7295
+ context.addIssue({ code: "custom", path: ["groupKey"], message: `${input.scope} scope does not accept groupKey.` });
7296
+ }
7297
+ if (input.scope !== "property" && input.targetKey) {
7298
+ context.addIssue({ code: "custom", path: ["targetKey"], message: `${input.scope} scope does not accept targetKey.` });
7299
+ }
7300
+ });
7301
+ var measurementPropertyEvidenceInputSchema = measurementPropertyEvidenceQuerySchema.extend({
7302
+ project: projectNameSchema,
7303
+ targetKey: measurementPropertyEvidenceQuerySchema.shape.targetKey.describe("Property stable key. Required \u2014 this read is scoped to exactly one Property.")
7304
+ }).strict();
7221
7305
  var measurementDraftCollectionInputSchema = measurementDraftCollectionQuerySchema.extend({ project: projectNameSchema });
7222
7306
  var measurementQuerySetInputSchema = z2.object({
7223
7307
  project: projectNameSchema,
@@ -7263,6 +7347,7 @@ var measurementDraftOperationSchema = z2.discriminatedUnion("action", [
7263
7347
  measurementDraftMutationOperationSchema("exclude-target", measurementDraftExcludeTargetRequestSchema),
7264
7348
  measurementDraftMutationOperationSchema("rebind-target", measurementDraftRebindTargetRequestSchema),
7265
7349
  measurementDraftMutationOperationSchema("apply-assignments", measurementDraftApplyAssignmentsRequestSchema),
7350
+ measurementDraftMutationOperationSchema("apply-paired-assignments", measurementDraftApplyPairedAssignmentsRequestSchema),
7266
7351
  measurementDraftMutationOperationSchema("remove-assignment", measurementDraftRemoveAssignmentRequestSchema),
7267
7352
  measurementDraftMutationOperationSchema("clear-assignments", measurementDraftClearAssignmentsRequestSchema),
7268
7353
  measurementDraftMutationOperationSchema("classify-assignments", measurementDraftClassifyAssignmentsRequestSchema),
@@ -7293,6 +7378,7 @@ var measurementDraftActionOpenApiOperations = [
7293
7378
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/exclude-target",
7294
7379
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/rebind-target",
7295
7380
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/apply-assignments",
7381
+ "POST /api/v1/projects/{name}/measurement-plan/draft/actions/apply-paired-assignments",
7296
7382
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/remove-assignment",
7297
7383
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/clear-assignments",
7298
7384
  "POST /api/v1/projects/{name}/measurement-plan/draft/actions/classify-assignments",
@@ -7326,6 +7412,8 @@ function runMeasurementDraftAction(client2, input) {
7326
7412
  return client2.rebindMeasurementDraftTarget(project, actionInput.request, actionInput.idempotencyKey, actionInput.etag);
7327
7413
  case "apply-assignments":
7328
7414
  return client2.applyMeasurementDraftAssignments(project, actionInput.request, actionInput.idempotencyKey, actionInput.etag);
7415
+ case "apply-paired-assignments":
7416
+ return client2.applyPairedMeasurementDraftAssignments(project, actionInput.request, actionInput.idempotencyKey, actionInput.etag);
7329
7417
  case "remove-assignment":
7330
7418
  return client2.removeMeasurementDraftAssignment(project, actionInput.request, actionInput.idempotencyKey, actionInput.etag);
7331
7419
  case "clear-assignments":
@@ -9020,7 +9108,7 @@ var canonryMcpTools = [
9020
9108
  defineTool({
9021
9109
  name: "canonry_measurement_overview",
9022
9110
  title: "Get Advanced Measurement overview",
9023
- description: "Return stored, revision-pinned Advanced Measurement metrics and a bounded page of Target rows for one scope. 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.",
9111
+ description: "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. 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.",
9024
9112
  access: "read",
9025
9113
  tier: "setup",
9026
9114
  inputSchema: measurementOverviewInputSchema,
@@ -9031,6 +9119,20 @@ var canonryMcpTools = [
9031
9119
  return client2.getMeasurementOverview(project, query);
9032
9120
  }
9033
9121
  }),
9122
+ defineTool({
9123
+ name: "canonry_measurement_property_evidence",
9124
+ title: "Page one Property's measurement evidence",
9125
+ description: "Return the stored source-evidence rows for exactly one Property out of one revision-pinned run, optionally narrowed to a question class, provider, or location. Prefer this over canonry_measurement_report when you want one Property: the report reconstructs every group and every Target for a revision and does not paginate. Run selection matches canonry_measurement_overview \u2014 the most recent completed run pinned to the active revision unless runId names another, and a run pinned to a different revision is refused rather than joined. The cursor pins the active revision, displayed run, evidence snapshot, and filters; reuse it unchanged. Not available for a schema v1 revision, which records no question class to scope by. It never starts provider work; page size is at most 100. An empty page under measurement.state = not_measured means the Property has not been measured at all, which is NOT a measured result of zero.",
9126
+ access: "read",
9127
+ tier: "setup",
9128
+ inputSchema: measurementPropertyEvidenceInputSchema,
9129
+ annotations: readAnnotations(),
9130
+ openApiOperations: ["GET /api/v1/projects/{name}/measurement-property-evidence"],
9131
+ handler: (client2, input) => {
9132
+ const { project, ...query } = input;
9133
+ return client2.getMeasurementPropertyEvidence(project, query);
9134
+ }
9135
+ }),
9034
9136
  defineTool({
9035
9137
  name: "canonry_measurement_draft_get",
9036
9138
  title: "Get Advanced Measurement draft",
@@ -9204,13 +9306,13 @@ var canonryMcpTools = [
9204
9306
  defineTool({
9205
9307
  name: "canonry_measurement_report",
9206
9308
  title: "Get measurement report",
9207
- description: "Get a revision-pinned Target and group measurement report from stored runs. Never starts live provider work.",
9309
+ 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.",
9208
9310
  access: "read",
9209
9311
  tier: "setup",
9210
- inputSchema: measurementPlanVersionInputSchema,
9312
+ inputSchema: measurementReportInputSchema,
9211
9313
  annotations: readAnnotations(),
9212
9314
  openApiOperations: ["GET /api/v1/projects/{name}/measurement-report"],
9213
- handler: (client2, input) => client2.getMeasurementReport(input.project, input.revision)
9315
+ handler: (client2, input) => client2.getMeasurementReport(input.project, input.revision, input.runId)
9214
9316
  }),
9215
9317
  defineTool({
9216
9318
  name: "canonry_run_trigger",
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-MBLATP5L.js";
13
+ } from "./chunk-UQOTEIA6.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -126,7 +126,7 @@ import {
126
126
  siteAuditSnapshots,
127
127
  toAlertView,
128
128
  usageCounters
129
- } from "./chunk-GTBCGJNT.js";
129
+ } from "./chunk-ED7C5TWT.js";
130
130
  import {
131
131
  AGENT_MEMORY_VALUE_MAX_BYTES,
132
132
  AGENT_PROVIDER_IDS,
@@ -217,7 +217,7 @@ import {
217
217
  validationError,
218
218
  winnabilityClassLabel,
219
219
  withRetry
220
- } from "./chunk-EFBTZ6ZT.js";
220
+ } from "./chunk-B5H55ZMA.js";
221
221
 
222
222
  // src/telemetry.ts
223
223
  import crypto from "crypto";
@@ -7420,7 +7420,7 @@ function readStoredGroundingSources(rawResponse) {
7420
7420
  return result;
7421
7421
  }
7422
7422
  async function backfillInsightsCommand(project, opts) {
7423
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-DVMEVHAG.js");
7423
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-M5UNHF7X.js");
7424
7424
  const config = loadConfig();
7425
7425
  const db = createClient(config.database);
7426
7426
  migrate(db);
package/dist/cli.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  showFirstRunNotice,
31
31
  trackCliCommandFinished,
32
32
  trackEvent
33
- } from "./chunk-XNAJXSZ2.js";
33
+ } from "./chunk-Z7B6BRPP.js";
34
34
  import {
35
35
  CliError,
36
36
  EXIT_SYSTEM_ERROR,
@@ -47,7 +47,7 @@ import {
47
47
  saveConfig,
48
48
  saveConfigPatch,
49
49
  usageError
50
- } from "./chunk-MBLATP5L.js";
50
+ } from "./chunk-UQOTEIA6.js";
51
51
  import {
52
52
  apiKeys,
53
53
  createClient,
@@ -55,7 +55,7 @@ import {
55
55
  projects,
56
56
  queries,
57
57
  renderReportHtml
58
- } from "./chunk-GTBCGJNT.js";
58
+ } from "./chunk-ED7C5TWT.js";
59
59
  import {
60
60
  AdsDeliverySnapshotStatuses,
61
61
  AdsHistoricalCampaignRollupStatuses,
@@ -106,7 +106,7 @@ import {
106
106
  providerQuotaPolicySchema,
107
107
  resolveProviderInput,
108
108
  winnabilityClassSchema
109
- } from "./chunk-EFBTZ6ZT.js";
109
+ } from "./chunk-B5H55ZMA.js";
110
110
 
111
111
  // src/cli.ts
112
112
  import { pathToFileURL } from "url";
@@ -15756,8 +15756,131 @@ async function discoverMeasurementTargets(project, sitemapUrl, ruleSource, maxUr
15756
15756
  async function showMeasurementReport(project, revision) {
15757
15757
  console.log(JSON.stringify(await createApiClient().getMeasurementReport(project, revision), null, 2));
15758
15758
  }
15759
+ var METRIC_REASONS = {
15760
+ plan_v1: "not measured (setup update required)",
15761
+ no_completed_run: "not measured (no completed run)",
15762
+ no_population: "not measured (no questions of this type)",
15763
+ evidence_incomplete: "not measured (evidence incomplete)",
15764
+ not_applicable: "not measured (not applicable)"
15765
+ };
15766
+ function metricText(metric) {
15767
+ if (metric.state === "unavailable") return METRIC_REASONS[metric.reason] ?? `not measured (${metric.reason})`;
15768
+ const percent = `${Math.round(metric.value * 100)}%`;
15769
+ return metric.numerator === void 0 || metric.denominator === void 0 ? percent : `${metric.numerator} of ${metric.denominator} (${percent})`;
15770
+ }
15771
+ async function showMeasurementProperty(project, opts) {
15772
+ const response = await createApiClient().getMeasurementOverview(project, {
15773
+ scope: "property",
15774
+ targetKey: opts.targetKey,
15775
+ ...opts.queryClass === void 0 ? {} : { queryClass: opts.queryClass },
15776
+ ...opts.provider === void 0 ? {} : { provider: opts.provider },
15777
+ ...opts.location === void 0 ? {} : { location: opts.location },
15778
+ ...opts.runId === void 0 ? {} : { runId: opts.runId }
15779
+ });
15780
+ if (isMachineFormat(opts.format)) {
15781
+ console.log(JSON.stringify(response, null, 2));
15782
+ return;
15783
+ }
15784
+ printMeasurementProperty(response);
15785
+ }
15786
+ function printMeasurementProperty(response) {
15787
+ const row = response.properties.items.at(0);
15788
+ const lines = [];
15789
+ lines.push(`${response.scope.label} \u2014 ${response.queryClass} questions`);
15790
+ lines.push(`Measurement: ${response.measurement.state}${response.measurement.displayedRunId ? ` \xB7 run ${response.measurement.displayedRunId}` : ""}`);
15791
+ lines.push("");
15792
+ lines.push(`Mentioned ${metricText(row ? row.mentionCoverage : response.metrics.mentionCoverage)}`);
15793
+ lines.push(`Cited ${metricText(row ? row.citationCoverage : response.metrics.citationCoverage)}`);
15794
+ if (row && row.flags > 0) lines.push(`Flagged ${row.flags} ${row.flags === 1 ? "result needs" : "results need"} review`);
15795
+ if (row && row.providers.length > 0) {
15796
+ lines.push("");
15797
+ lines.push(`${"Engine".padEnd(14)}${"Mentioned".padEnd(34)}Cited`);
15798
+ for (const provider of row.providers) {
15799
+ lines.push(`${provider.provider.padEnd(14)}${metricText(provider.mentionCoverage).padEnd(34)}${metricText(provider.citationCoverage)}`);
15800
+ }
15801
+ }
15802
+ console.log(lines.join("\n"));
15803
+ }
15804
+ async function showMeasurementPropertyEvidence(project, opts) {
15805
+ const response = await createApiClient().getMeasurementPropertyEvidence(project, {
15806
+ targetKey: opts.targetKey,
15807
+ ...opts.queryClass === void 0 ? {} : { queryClass: opts.queryClass },
15808
+ ...opts.provider === void 0 ? {} : { provider: opts.provider },
15809
+ ...opts.location === void 0 ? {} : { location: opts.location },
15810
+ ...opts.runId === void 0 ? {} : { runId: opts.runId },
15811
+ ...opts.cursor === void 0 ? {} : { cursor: opts.cursor },
15812
+ ...opts.limit === void 0 ? {} : { limit: opts.limit }
15813
+ });
15814
+ if (opts.format === "jsonl") {
15815
+ emitJsonl([{
15816
+ kind: "measurement-property-evidence-header",
15817
+ property: response.property,
15818
+ queryClass: response.queryClass,
15819
+ measurement: response.measurement,
15820
+ totalEstimate: response.evidence.totalEstimate ?? null,
15821
+ nextCursor: response.evidence.nextCursor ?? null
15822
+ }]);
15823
+ emitJsonl(response.evidence.items);
15824
+ return;
15825
+ }
15826
+ if (opts.format === "json") {
15827
+ console.log(JSON.stringify(response, null, 2));
15828
+ return;
15829
+ }
15830
+ printMeasurementPropertyEvidence(response);
15831
+ }
15832
+ function printMeasurementPropertyEvidence(response) {
15833
+ const lines = [];
15834
+ lines.push(`${response.property.label} \u2014 ${response.queryClass} questions`);
15835
+ if (response.measurement.state === "not_measured") {
15836
+ lines.push("Not measured yet. Run a measurement to collect source evidence.");
15837
+ console.log(lines.join("\n"));
15838
+ return;
15839
+ }
15840
+ const page = response.evidence;
15841
+ lines.push(`Measurement: ${response.measurement.state}${response.measurement.displayedRunId ? ` \xB7 run ${response.measurement.displayedRunId}` : ""}`);
15842
+ if (page.items.length === 0) {
15843
+ lines.push("No source evidence matched this Property in the displayed run.");
15844
+ console.log(lines.join("\n"));
15845
+ return;
15846
+ }
15847
+ lines.push(`${page.items.length} of ${page.totalEstimate ?? page.items.length} evidence rows`);
15848
+ lines.push("");
15849
+ lines.push(`${"Match".padEnd(14)}${"Engine".padEnd(12)}${"Question".padEnd(40)}URL`);
15850
+ for (const item of page.items) {
15851
+ lines.push(`${item.classification.padEnd(14)}${item.provider.padEnd(12)}${item.queryText.slice(0, 39).padEnd(40)}${item.sourceUrl}`);
15852
+ }
15853
+ if (page.nextCursor) lines.push(`
15854
+ More rows: --cursor ${page.nextCursor}`);
15855
+ console.log(lines.join("\n"));
15856
+ }
15759
15857
 
15760
15858
  // src/cli-commands/measurement-plan.ts
15859
+ var QUERY_CLASSES = ["all", "branded", "non-brand"];
15860
+ function queryClassOption(input) {
15861
+ const value = getString(input.values, "query-class");
15862
+ if (value === void 0) return void 0;
15863
+ const match = QUERY_CLASSES.find((candidate) => candidate === value);
15864
+ if (!match) throw usageError(`--query-class must be one of ${QUERY_CLASSES.join(", ")}`);
15865
+ return match;
15866
+ }
15867
+ function propertyScope(input, command, usage) {
15868
+ return {
15869
+ targetKey: requireStringOption(input, "target-key", { command, usage, message: "--target-key is required" }),
15870
+ queryClass: queryClassOption(input),
15871
+ provider: getString(input.values, "provider"),
15872
+ location: getString(input.values, "location"),
15873
+ runId: getString(input.values, "run-id"),
15874
+ format: input.format
15875
+ };
15876
+ }
15877
+ var PROPERTY_SCOPE_OPTIONS = {
15878
+ "target-key": stringOption(),
15879
+ "query-class": stringOption(),
15880
+ provider: stringOption(),
15881
+ location: stringOption(),
15882
+ "run-id": stringOption()
15883
+ };
15761
15884
  var MEASUREMENT_PLAN_CLI_COMMANDS = [
15762
15885
  { path: ["measurement-plan", "show"], usage: "canonry measurement-plan show <project> [--revision N] [--format json]", options: { revision: stringOption() }, run: async (input) => {
15763
15886
  const value = getString(input.values, "revision");
@@ -15816,6 +15939,35 @@ var MEASUREMENT_PLAN_CLI_COMMANDS = [
15816
15939
  }
15817
15940
  return showMeasurementReport(project, revision);
15818
15941
  }
15942
+ },
15943
+ {
15944
+ path: ["measurement-plan", "property"],
15945
+ usage: "canonry measurement-plan property <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--format json]",
15946
+ options: PROPERTY_SCOPE_OPTIONS,
15947
+ run: (input) => {
15948
+ const usage = "canonry measurement-plan property <project> --target-key <key>";
15949
+ const project = requireProject(input, "measurement-plan.property", usage);
15950
+ return showMeasurementProperty(project, propertyScope(input, "measurement-plan.property", usage));
15951
+ }
15952
+ },
15953
+ {
15954
+ path: ["measurement-plan", "property-evidence"],
15955
+ usage: "canonry measurement-plan property-evidence <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--cursor <c>] [--limit N] [--format json|jsonl]",
15956
+ options: { ...PROPERTY_SCOPE_OPTIONS, cursor: stringOption(), limit: stringOption() },
15957
+ run: (input) => {
15958
+ const usage = "canonry measurement-plan property-evidence <project> --target-key <key>";
15959
+ const project = requireProject(input, "measurement-plan.property-evidence", usage);
15960
+ const limitValue = getString(input.values, "limit");
15961
+ const limit = limitValue === void 0 ? void 0 : Number(limitValue);
15962
+ if (limit !== void 0 && (!Number.isInteger(limit) || limit < 1 || limit > 100)) {
15963
+ throw usageError("--limit must be an integer from 1 to 100");
15964
+ }
15965
+ return showMeasurementPropertyEvidence(project, {
15966
+ ...propertyScope(input, "measurement-plan.property-evidence", usage),
15967
+ cursor: getString(input.values, "cursor"),
15968
+ ...limit === void 0 ? {} : { limit }
15969
+ });
15970
+ }
15819
15971
  }
15820
15972
  ];
15821
15973
 
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-XNAJXSZ2.js";
3
+ } from "./chunk-Z7B6BRPP.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-MBLATP5L.js";
7
- import "./chunk-GTBCGJNT.js";
8
- import "./chunk-EFBTZ6ZT.js";
6
+ } from "./chunk-UQOTEIA6.js";
7
+ import "./chunk-ED7C5TWT.js";
8
+ import "./chunk-B5H55ZMA.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-GTBCGJNT.js";
4
- import "./chunk-EFBTZ6ZT.js";
3
+ } from "./chunk-ED7C5TWT.js";
4
+ import "./chunk-B5H55ZMA.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-MBLATP5L.js";
6
+ } from "./chunk-UQOTEIA6.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-EFBTZ6ZT.js";
9
+ } from "./chunk-B5H55ZMA.js";
10
10
 
11
11
  // src/mcp/cli.ts
12
12
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "4.145.0",
3
+ "version": "4.146.0",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -67,25 +67,25 @@
67
67
  "tsx": "^4.19.0",
68
68
  "@ainyc/canonry-api-client": "0.0.0",
69
69
  "@ainyc/canonry-api-routes": "0.0.0",
70
- "@ainyc/canonry-config": "0.0.0",
71
70
  "@ainyc/canonry-contracts": "0.0.0",
72
71
  "@ainyc/canonry-db": "0.0.0",
73
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
72
+ "@ainyc/canonry-config": "0.0.0",
74
73
  "@ainyc/canonry-integration-bing": "0.0.0",
74
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
75
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
75
76
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
76
- "@ainyc/canonry-integration-google": "0.0.0",
77
77
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
78
- "@ainyc/canonry-integration-google-places": "0.0.0",
79
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
78
+ "@ainyc/canonry-integration-google": "0.0.0",
79
+ "@ainyc/canonry-integration-traffic": "0.0.0",
80
80
  "@ainyc/canonry-integration-wordpress": "0.0.0",
81
+ "@ainyc/canonry-integration-google-places": "0.0.0",
81
82
  "@ainyc/canonry-intelligence": "0.0.0",
82
- "@ainyc/canonry-integration-traffic": "0.0.0",
83
- "@ainyc/canonry-provider-cdp": "0.0.0",
83
+ "@ainyc/canonry-provider-gemini": "0.0.0",
84
84
  "@ainyc/canonry-provider-claude": "0.0.0",
85
+ "@ainyc/canonry-provider-cdp": "0.0.0",
85
86
  "@ainyc/canonry-provider-local": "0.0.0",
86
- "@ainyc/canonry-provider-gemini": "0.0.0",
87
- "@ainyc/canonry-provider-perplexity": "0.0.0",
88
- "@ainyc/canonry-provider-openai": "0.0.0"
87
+ "@ainyc/canonry-provider-openai": "0.0.0",
88
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
89
89
  },
90
90
  "scripts": {
91
91
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",