@canonry/canonry 4.144.0 → 4.145.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 (24) hide show
  1. package/assets/assets/{AuditHistoryPanel-DxRP9WsD.js → AuditHistoryPanel-CV9g5mLR.js} +1 -1
  2. package/assets/assets/{BacklinksPage-yiEbyV67.js → BacklinksPage-RTcYKA5I.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-D2hRlMHn.js → ChartPrimitives-BMR0Dqnf.js} +1 -1
  4. package/assets/assets/{HistoryPage-CW6MJ-dR.js → HistoryPage-DAN9QO6x.js} +1 -1
  5. package/assets/assets/{ProjectPage-Bnr7I5qu.js → ProjectPage-aFV2nddp.js} +1 -1
  6. package/assets/assets/{RunRow-Dr607W0P.js → RunRow-WDCIS9MJ.js} +1 -1
  7. package/assets/assets/{RunsPage-CtF3P7CA.js → RunsPage-D3Zxd6oc.js} +1 -1
  8. package/assets/assets/{SettingsPage-3-uzs2lp.js → SettingsPage-DcCFVeA7.js} +1 -1
  9. package/assets/assets/{TrafficPage-Bww4KUn8.js → TrafficPage-D0tPBu5O.js} +1 -1
  10. package/assets/assets/{TrafficSourceDetailPage-DiHxUH2H.js → TrafficSourceDetailPage-CtyEE9eJ.js} +1 -1
  11. package/assets/assets/{arrow-left-D-PcVbQ4.js → arrow-left-hBxXIGS1.js} +1 -1
  12. package/assets/assets/{extract-error-message-BRq0yLWg.js → extract-error-message-DRu89RHb.js} +1 -1
  13. package/assets/assets/{index-b5M4QpB0.js → index-DSOfEiTH.js} +42 -42
  14. package/assets/assets/{trash-2-B6aJTnJl.js → trash-2-DP0ukgbl.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-WADGZMWT.js → chunk-EFBTZ6ZT.js} +14 -0
  17. package/dist/{chunk-7D2GZU6O.js → chunk-GTBCGJNT.js} +194 -25
  18. package/dist/{chunk-Z672VQ7G.js → chunk-MBLATP5L.js} +1250 -70
  19. package/dist/{chunk-3NYTF3YC.js → chunk-XNAJXSZ2.js} +4 -4
  20. package/dist/cli.js +4 -4
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-OLIGR6HE.js → intelligence-service-DVMEVHAG.js} +2 -2
  23. package/dist/mcp.js +5 -5
  24. package/package.json +10 -10
@@ -1 +1 @@
1
- import{c as a}from"./index-b5M4QpB0.js";const t=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],h=a("circle-question-mark",t);const e=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],d=a("download",e);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],p=a("external-link",o);const c=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],s=a("trash-2",c);export{h as C,d as D,p as E,s as T};
1
+ import{c as a}from"./index-DSOfEiTH.js";const t=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],h=a("circle-question-mark",t);const e=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],d=a("download",e);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],p=a("external-link",o);const c=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],s=a("trash-2",c);export{h as C,d as D,p as E,s as T};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-b5M4QpB0.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-DSOfEiTH.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Be8JdV5M.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-CQ77EO2y.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-DSxTZhaH.js">
@@ -3980,6 +3980,15 @@ var measurementMetricValueSchema = z5.discriminatedUnion("state", [
3980
3980
  ]);
3981
3981
  var measurementOverviewScopeKindSchema = z5.enum(["all", "group", "property"]);
3982
3982
  var measurementQueryClassFilterSchema = z5.enum(["all", "branded", "non-brand"]);
3983
+ var measurementOverviewSortSchema = z5.enum([
3984
+ "label-asc",
3985
+ "label-desc",
3986
+ "citationCoverage-asc",
3987
+ "citationCoverage-desc",
3988
+ "mentionCoverage-asc",
3989
+ "mentionCoverage-desc"
3990
+ ]);
3991
+ var MEASUREMENT_OVERVIEW_DEFAULT_SORT = "label-asc";
3983
3992
  var measurementStateSchema = z5.enum(["not_measured", "queued", "running", "complete", "partial", "failed"]);
3984
3993
  var measurementNextActionKindSchema = z5.enum([
3985
3994
  "run_measurement",
@@ -4000,6 +4009,8 @@ var measurementOverviewQuerySchema = z5.object({
4000
4009
  runId: z5.string().trim().min(1).optional(),
4001
4010
  /** Filters the returned rows only. Metrics are computed before it is applied. */
4002
4011
  search: z5.string().optional(),
4012
+ /** Omit for the shipped label-ascending order. Metric-unavailable rows sort first. */
4013
+ sort: measurementOverviewSortSchema.optional(),
4003
4014
  cursor: z5.string().trim().min(1).optional(),
4004
4015
  limit: z5.number().int().positive().max(MEASUREMENT_PAGE_MAX_LIMIT).optional()
4005
4016
  }).strict();
@@ -13067,6 +13078,8 @@ export {
13067
13078
  measurementPlanV2ChecksumJson,
13068
13079
  MEASUREMENT_PAGE_DEFAULT_LIMIT,
13069
13080
  MEASUREMENT_PAGE_MAX_LIMIT,
13081
+ measurementOverviewSortSchema,
13082
+ MEASUREMENT_OVERVIEW_DEFAULT_SORT,
13070
13083
  measurementOverviewQuerySchema,
13071
13084
  measurementOverviewResponseSchema,
13072
13085
  measurementStableKeySchema,
@@ -13110,6 +13123,7 @@ export {
13110
13123
  measurementDraftTargetPageSchema,
13111
13124
  measurementDraftAssignmentPageSchema,
13112
13125
  measurementDraftGroupPageSchema,
13126
+ measurementDraftCollectionQuerySchema,
13113
13127
  measurementDraftCreateRequestSchema,
13114
13128
  measurementDraftImportSitemapRequestSchema,
13115
13129
  measurementDraftApplySitemapSelectionRequestSchema,
@@ -48,6 +48,7 @@ import {
48
48
  DiscoveryCompetitorTypes,
49
49
  DiscoverySessionStatuses,
50
50
  LOGIN_FAILED_MESSAGE,
51
+ MEASUREMENT_OVERVIEW_DEFAULT_SORT,
51
52
  MEASUREMENT_PAGE_DEFAULT_LIMIT,
52
53
  MEASUREMENT_PAGE_MAX_LIMIT,
53
54
  MEASUREMENT_PLAN_V2_SCHEMA_VERSION,
@@ -323,6 +324,7 @@ import {
323
324
  measurementIdempotencyKeyRequired,
324
325
  measurementOverviewQuerySchema,
325
326
  measurementOverviewResponseSchema,
327
+ measurementOverviewSortSchema,
326
328
  measurementPlanAuthoringSchema,
327
329
  measurementPlanCompilePreviewResponseSchema,
328
330
  measurementPlanCounts,
@@ -483,7 +485,7 @@ import {
483
485
  wordpressSchemaDeployResultDtoSchema,
484
486
  wordpressSchemaStatusResultDtoSchema,
485
487
  wordpressStatusDtoSchema
486
- } from "./chunk-WADGZMWT.js";
488
+ } from "./chunk-EFBTZ6ZT.js";
487
489
 
488
490
  // src/intelligence-service.ts
489
491
  import { eq as eq54, desc as desc25, asc as asc11, and as and42, ne as ne7, or as or10, inArray as inArray17, gte as gte13, lte as lte10 } from "drizzle-orm";
@@ -14019,6 +14021,7 @@ async function measurementDiscoveryV2Routes(app) {
14019
14021
  }
14020
14022
 
14021
14023
  // ../api-routes/src/measurement-overview.ts
14024
+ import { createHash } from "crypto";
14022
14025
  import { and as and11, eq as eq17 } from "drizzle-orm";
14023
14026
 
14024
14027
  // ../api-routes/src/measurement-run-completeness.ts
@@ -14098,29 +14101,149 @@ function countMetric(rate) {
14098
14101
  function normalizedText(value) {
14099
14102
  return value.normalize("NFKC").trim().replace(/\s+/g, " ").toLocaleLowerCase("en");
14100
14103
  }
14101
- function compareRows(left, right) {
14104
+ function overviewFilterFingerprint(query) {
14105
+ const filters = {
14106
+ scope: query.scope,
14107
+ groupKey: query.groupKey ?? null,
14108
+ targetKey: query.targetKey ?? null,
14109
+ queryClass: query.queryClass ?? "all",
14110
+ provider: query.provider === void 0 ? null : normalizedText(query.provider),
14111
+ location: query.location === void 0 ? null : normalizedText(query.location),
14112
+ from: query.from ?? null,
14113
+ to: query.to ?? null,
14114
+ search: query.search === void 0 ? null : normalizedText(query.search)
14115
+ };
14116
+ return createHash("sha256").update(JSON.stringify(filters)).digest("base64url");
14117
+ }
14118
+ function overviewEvidenceFingerprint(snapshots) {
14119
+ const canonical = [...snapshots].sort((left, right) => left.id.localeCompare(right.id)).map((snapshot) => JSON.stringify(snapshot)).join("\n");
14120
+ return createHash("sha256").update(canonical).digest("base64url");
14121
+ }
14122
+ function compareLabels(left, right) {
14102
14123
  const leftLabel = normalizedText(left.label);
14103
14124
  const rightLabel = normalizedText(right.label);
14104
14125
  if (leftLabel !== rightLabel) return leftLabel < rightLabel ? -1 : 1;
14105
14126
  return left.targetKey < right.targetKey ? -1 : left.targetKey > right.targetKey ? 1 : 0;
14106
14127
  }
14107
- function cursorOf(row) {
14128
+ function compareLabelSort(left, right, descending) {
14129
+ const leftLabel = normalizedText(left.label);
14130
+ const rightLabel = normalizedText(right.label);
14131
+ if (leftLabel !== rightLabel) {
14132
+ const compared = leftLabel < rightLabel ? -1 : 1;
14133
+ return descending ? -compared : compared;
14134
+ }
14135
+ return left.targetKey < right.targetKey ? -1 : left.targetKey > right.targetKey ? 1 : 0;
14136
+ }
14137
+ function metricForSort(row, sort) {
14138
+ switch (sort) {
14139
+ case "citationCoverage-asc":
14140
+ case "citationCoverage-desc":
14141
+ return row.citationCoverage;
14142
+ case "mentionCoverage-asc":
14143
+ case "mentionCoverage-desc":
14144
+ return row.mentionCoverage;
14145
+ case "label-asc":
14146
+ case "label-desc":
14147
+ return null;
14148
+ }
14149
+ }
14150
+ function compareRows(left, right, sort) {
14151
+ if (sort === "label-asc" || sort === "label-desc") {
14152
+ return compareLabelSort(left, right, sort === "label-desc");
14153
+ }
14154
+ const leftMetric = metricForSort(left, sort);
14155
+ const rightMetric = metricForSort(right, sort);
14156
+ if (leftMetric.state !== rightMetric.state) return leftMetric.state === "unavailable" ? -1 : 1;
14157
+ if (leftMetric.state === "available" && rightMetric.state === "available" && leftMetric.value !== rightMetric.value) {
14158
+ const compared = leftMetric.value < rightMetric.value ? -1 : 1;
14159
+ return sort.endsWith("-desc") ? -compared : compared;
14160
+ }
14161
+ return compareLabels(left, right);
14162
+ }
14163
+ function legacyCursorOf(row) {
14108
14164
  return Buffer.from(`${normalizedText(row.label)}:${row.targetKey}`, "utf8").toString("base64url");
14109
14165
  }
14110
- function pageOf(rows, query) {
14166
+ function cursorOf(row, sort, displayedRunId, filterFingerprint, planVersionId, evidenceFingerprint) {
14167
+ const cursor = {
14168
+ v: 1,
14169
+ sort,
14170
+ targetKey: row.targetKey,
14171
+ displayedRunId,
14172
+ filterFingerprint,
14173
+ planVersionId,
14174
+ evidenceFingerprint
14175
+ };
14176
+ return Buffer.from(JSON.stringify(cursor), "utf8").toString("base64url");
14177
+ }
14178
+ function parseCursor(value) {
14179
+ try {
14180
+ const parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
14181
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
14182
+ const cursor = parsed;
14183
+ if (cursor.v !== 1 || typeof cursor.targetKey !== "string" || !measurementOverviewSortSchema.safeParse(cursor.sort).success) return null;
14184
+ if (cursor.displayedRunId !== null && typeof cursor.displayedRunId !== "string") return null;
14185
+ if (typeof cursor.filterFingerprint !== "string" || cursor.filterFingerprint.length === 0) return null;
14186
+ if (typeof cursor.planVersionId !== "string" || cursor.planVersionId.length === 0) return null;
14187
+ if (typeof cursor.evidenceFingerprint !== "string" || cursor.evidenceFingerprint.length === 0) return null;
14188
+ return {
14189
+ v: 1,
14190
+ sort: cursor.sort,
14191
+ targetKey: cursor.targetKey,
14192
+ displayedRunId: cursor.displayedRunId,
14193
+ filterFingerprint: cursor.filterFingerprint,
14194
+ planVersionId: cursor.planVersionId,
14195
+ evidenceFingerprint: cursor.evidenceFingerprint
14196
+ };
14197
+ } catch {
14198
+ return null;
14199
+ }
14200
+ }
14201
+ function validatedCursor(query, activePlanVersionId) {
14202
+ if (query.cursor === void 0) return null;
14203
+ const cursor = parseCursor(query.cursor);
14204
+ if (cursor === null) return null;
14205
+ const sort = query.sort ?? MEASUREMENT_OVERVIEW_DEFAULT_SORT;
14206
+ if (cursor.sort !== sort) {
14207
+ throw validationError("The measurement overview cursor sort does not match the request.");
14208
+ }
14209
+ if (cursor.filterFingerprint !== overviewFilterFingerprint(query)) {
14210
+ throw validationError("The measurement overview cursor filters do not match the request.");
14211
+ }
14212
+ if (query.runId !== void 0 && cursor.displayedRunId !== query.runId) {
14213
+ throw validationError("The measurement overview cursor run does not match the request.");
14214
+ }
14215
+ if (cursor.planVersionId !== activePlanVersionId) {
14216
+ throw validationError("The measurement overview cursor revision does not match the active plan.");
14217
+ }
14218
+ return cursor;
14219
+ }
14220
+ function pageOf(rows, query, displayedRunId, activePlanVersionId, evidenceFingerprint) {
14221
+ const sort = query.sort ?? MEASUREMENT_OVERVIEW_DEFAULT_SORT;
14222
+ const ordered = [...rows].sort((left, right) => compareRows(left, right, sort));
14111
14223
  const limit = query.limit ?? MEASUREMENT_PAGE_DEFAULT_LIMIT;
14112
14224
  let offset = 0;
14113
14225
  if (query.cursor !== void 0) {
14114
- const index2 = rows.findIndex((row) => cursorOf(row) === query.cursor);
14226
+ const cursor = validatedCursor(query, activePlanVersionId);
14227
+ if (cursor !== null && cursor.evidenceFingerprint !== evidenceFingerprint) {
14228
+ throw validationError("The measurement overview cursor evidence changed between pages.");
14229
+ }
14230
+ const index2 = cursor === null ? query.sort === void 0 ? ordered.findIndex((row) => legacyCursorOf(row) === query.cursor) : -1 : ordered.findIndex((row) => row.targetKey === cursor.targetKey);
14115
14231
  if (index2 < 0) throw validationError("The measurement overview cursor does not belong to this result set.");
14116
14232
  offset = index2 + 1;
14117
14233
  }
14118
- const items = rows.slice(offset, offset + limit);
14234
+ const items = ordered.slice(offset, offset + limit);
14119
14235
  const last = items.at(-1);
14120
14236
  return {
14121
14237
  items,
14122
- nextCursor: last === void 0 || rows.at(offset + limit) === void 0 ? null : cursorOf(last),
14123
- totalEstimate: rows.length
14238
+ nextCursor: last === void 0 || ordered.at(offset + limit) === void 0 ? null : cursorOf(
14239
+ last,
14240
+ sort,
14241
+ displayedRunId,
14242
+ overviewFilterFingerprint(query),
14243
+ activePlanVersionId,
14244
+ evidenceFingerprint
14245
+ ),
14246
+ totalEstimate: ordered.length
14124
14247
  };
14125
14248
  }
14126
14249
  function runRevisionMismatch(runId, runRevision, activeRevision) {
@@ -14156,14 +14279,17 @@ function windowBound(value, endOfDay) {
14156
14279
  return `${value}${endOfDay ? "T23:59:59.999Z" : "T00:00:00.000Z"}`;
14157
14280
  }
14158
14281
  function selectDisplayedRun(db, projectId, active, query) {
14159
- if (query.runId === void 0) {
14282
+ const cursor = validatedCursor(query, active.version.id);
14283
+ const selectedRunId = query.runId ?? cursor?.displayedRunId;
14284
+ if (selectedRunId === null) return void 0;
14285
+ if (selectedRunId === void 0) {
14160
14286
  return latestMeasurementRun(db, projectId, active.version.id, [RunStatuses.completed], {
14161
14287
  from: windowBound(query.from, false),
14162
14288
  to: windowBound(query.to, true)
14163
14289
  });
14164
14290
  }
14165
- const run = db.select().from(runs).where(and11(eq17(runs.projectId, projectId), eq17(runs.id, query.runId))).get();
14166
- if (!run) throw notFound("Run", query.runId);
14291
+ const run = db.select().from(runs).where(and11(eq17(runs.projectId, projectId), eq17(runs.id, selectedRunId))).get();
14292
+ if (!run) throw notFound("Run", selectedRunId);
14167
14293
  if (run.measurementPlanVersionId === active.version.id) return run;
14168
14294
  const pinned = run.measurementPlanVersionId === null ? null : db.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq17(measurementPlanVersions.id, run.measurementPlanVersionId)).get()?.revision ?? null;
14169
14295
  throw runRevisionMismatch(run.id, pinned, active.version.revision);
@@ -14237,7 +14363,7 @@ function matchesSearch(row, search) {
14237
14363
  }
14238
14364
  function propertyLabels(plan, scope) {
14239
14365
  const labels = new Map(plan.targets.map((target) => [target.stableKey, target.label]));
14240
- return scope.targetKeys.map((targetKey) => ({ targetKey, label: labels.get(targetKey) ?? targetKey })).sort(compareRows);
14366
+ return scope.targetKeys.map((targetKey) => ({ targetKey, label: labels.get(targetKey) ?? targetKey }));
14241
14367
  }
14242
14368
  function scopeDto(scope) {
14243
14369
  return { kind: scope.kind, ...scope.key === void 0 ? {} : { key: scope.key }, label: scope.label };
@@ -14248,7 +14374,7 @@ function runProgress(db, displayed, plan) {
14248
14374
  return { completed: completeness2.executed, expected: completeness2.expected };
14249
14375
  }
14250
14376
  function planV1Overview(db, projectId, active, query, scope) {
14251
- const displayed = latestMeasurementRun(db, projectId, active.version.id, [RunStatuses.completed]);
14377
+ const displayed = selectDisplayedRun(db, projectId, active, query);
14252
14378
  const page = pageOf(
14253
14379
  propertyLabels(active.plan, scope).filter((row) => matchesSearch(row, query.search)).map((row) => ({
14254
14380
  ...row,
@@ -14256,7 +14382,12 @@ function planV1Overview(db, projectId, active, query, scope) {
14256
14382
  citationCoverage: unavailable2("plan_v1"),
14257
14383
  flags: 0
14258
14384
  })),
14259
- query
14385
+ query,
14386
+ displayed?.id ?? null,
14387
+ active.version.id,
14388
+ // V1 rows are always plan_v1-unavailable and label/key ordered. Evidence
14389
+ // cannot change this page, so avoid materializing a full run merely to hash it.
14390
+ overviewEvidenceFingerprint([])
14260
14391
  );
14261
14392
  return {
14262
14393
  mode: "active-v1",
@@ -14293,7 +14424,10 @@ function planV2Overview(db, projectId, active, plan, query, scope) {
14293
14424
  citationCoverage: unavailable2("no_completed_run"),
14294
14425
  flags: 0
14295
14426
  })),
14296
- query
14427
+ query,
14428
+ null,
14429
+ active.version.id,
14430
+ overviewEvidenceFingerprint([])
14297
14431
  );
14298
14432
  return {
14299
14433
  mode: "active-v2",
@@ -14338,7 +14472,10 @@ function planV2Overview(db, projectId, active, plan, query, scope) {
14338
14472
  flags: property?.flags ?? 0
14339
14473
  };
14340
14474
  }),
14341
- query
14475
+ query,
14476
+ displayed.id,
14477
+ active.version.id,
14478
+ overviewEvidenceFingerprint(snapshots)
14342
14479
  );
14343
14480
  const credited = new Map((overview.namedShareOfVoice?.entries ?? []).map((entry) => [entry.key, entry]));
14344
14481
  const namedShareOfVoice = overview.namedShareOfVoice === null || scope.key === void 0 ? void 0 : {
@@ -24187,6 +24324,29 @@ var measurementCursorParameter = {
24187
24324
  description: "Opaque cursor from the previous page.",
24188
24325
  schema: stringSchema
24189
24326
  };
24327
+ var measurementOverviewSortParameter = {
24328
+ name: "sort",
24329
+ in: "query",
24330
+ description: "Snapshot row order. label-asc is the default. For coverage sorts, unavailable rows form the first bucket in either direction; available rates then follow the requested direction.",
24331
+ schema: {
24332
+ type: "string",
24333
+ enum: [
24334
+ "label-asc",
24335
+ "label-desc",
24336
+ "citationCoverage-asc",
24337
+ "citationCoverage-desc",
24338
+ "mentionCoverage-asc",
24339
+ "mentionCoverage-desc"
24340
+ ],
24341
+ default: "label-asc"
24342
+ }
24343
+ };
24344
+ var measurementOverviewCursorParameter = {
24345
+ name: "cursor",
24346
+ in: "query",
24347
+ description: "Opaque, sort-aware cursor from the previous page. It pins pagination to the active revision, displayed run, evidence snapshot, and same filters even if a newer run completes. Reuse it unchanged with the same sort and filters; a mismatch or newly appended evidence is rejected. A legacy label cursor works only when sort is omitted; an explicit sort requires a new sort-bound cursor.",
24348
+ schema: stringSchema
24349
+ };
24190
24350
  var measurementLimitParameter = {
24191
24351
  name: "limit",
24192
24352
  in: "query",
@@ -24214,7 +24374,12 @@ var measurementDraftCollectionParameters = [
24214
24374
  measurementLimitParameter
24215
24375
  ];
24216
24376
  function measurementDraftAction(input) {
24217
- const parameters = input.readOnly ? [nameParameter] : [nameParameter, measurementIfMatchParameter, measurementIdempotencyKeyParameter];
24377
+ const requiresDraftEtag = !input.readOnly && input.requiresDraftEtag !== false;
24378
+ const parameters = input.readOnly ? [nameParameter] : [
24379
+ nameParameter,
24380
+ ...requiresDraftEtag ? [measurementIfMatchParameter] : [],
24381
+ measurementIdempotencyKeyParameter
24382
+ ];
24218
24383
  return {
24219
24384
  method: "post",
24220
24385
  path: `/api/v1/projects/{name}/measurement-plan/draft/actions/${input.action}`,
@@ -24238,8 +24403,10 @@ function measurementDraftAction(input) {
24238
24403
  404: errorResponse("Project or draft not found."),
24239
24404
  ...input.readOnly ? {} : {
24240
24405
  409: errorResponse("The idempotency key was already used with a different request body."),
24241
- 412: errorResponse("The draft changed since it was loaded."),
24242
- 428: errorResponse("The draft ETag was not supplied in `If-Match`.")
24406
+ ...requiresDraftEtag ? {
24407
+ 412: errorResponse("The draft changed since it was loaded."),
24408
+ 428: errorResponse("The draft ETag was not supplied in `If-Match`.")
24409
+ } : {}
24243
24410
  }
24244
24411
  }
24245
24412
  };
@@ -24517,7 +24684,8 @@ var routeCatalog = [
24517
24684
  action: "create",
24518
24685
  summary: "Start a setup draft",
24519
24686
  description: "Creates the single draft for the project, recording the active revision it was created from. A draft never changes the active mode.",
24520
- request: "MeasurementDraftCreateRequest"
24687
+ request: "MeasurementDraftCreateRequest",
24688
+ requiresDraftEtag: false
24521
24689
  }),
24522
24690
  measurementDraftAction({
24523
24691
  action: "import-sitemap",
@@ -24657,7 +24825,7 @@ var routeCatalog = [
24657
24825
  method: "get",
24658
24826
  path: "/api/v1/projects/{name}/measurement-overview",
24659
24827
  summary: "Get the scoped measurement overview",
24660
- description: "Aggregates one run of evidence for All Properties, a group, or a single Property. Without runId the most recent completed run pinned to the active revision is used; a run pinned to another revision is refused rather than joined. Metrics are computed before search is applied, and a metric with no evidence is unavailable rather than zero.",
24828
+ description: "Aggregates one revision-pinned run snapshot for All Properties, a group, or a single Property. This is snapshot ranking only: it never infers a trend or compares evidence across revisions. Without runId the most recent completed run pinned to the active revision is used; once paging begins, the cursor pins that revision, displayed run, evidence snapshot, and result filters. A run pinned to another revision is refused rather than joined, and appended evidence on a mutable named run invalidates its cursor. Metrics are computed before search is applied, and a metric with no evidence is unavailable rather than zero. For coverage sorts, unavailable rows form the first bucket in either direction before available numeric rates follow the requested direction.",
24661
24829
  tags: ["measurement-plans"],
24662
24830
  parameters: [
24663
24831
  nameParameter,
@@ -24671,7 +24839,8 @@ var routeCatalog = [
24671
24839
  { name: "to", in: "query", description: "Inclusive end of the window (YYYY-MM-DD).", schema: stringSchema },
24672
24840
  { name: "runId", in: "query", description: "Display this run. It must be pinned to the active revision. This is also the only way to display a scoped spot check.", schema: stringSchema },
24673
24841
  measurementSearchParameter,
24674
- measurementCursorParameter,
24842
+ measurementOverviewSortParameter,
24843
+ measurementOverviewCursorParameter,
24675
24844
  measurementLimitParameter
24676
24845
  ],
24677
24846
  responses: {
@@ -42387,7 +42556,7 @@ function parseContentLength(value) {
42387
42556
  }
42388
42557
 
42389
42558
  // ../integration-commoncrawl/src/downloader.ts
42390
- import { createHash } from "crypto";
42559
+ import { createHash as createHash2 } from "crypto";
42391
42560
  import { createWriteStream } from "fs";
42392
42561
  import fs2 from "fs/promises";
42393
42562
  import path3 from "path";
@@ -42413,7 +42582,7 @@ async function downloadFile(opts) {
42413
42582
  throw new Error(`HTTP ${res.status} ${res.statusText} for ${opts.url}`);
42414
42583
  }
42415
42584
  const total = parseContentLength2(res.headers.get("content-length"));
42416
- const hasher = createHash("sha256");
42585
+ const hasher = createHash2("sha256");
42417
42586
  let bytes = 0;
42418
42587
  const hashAndCount = new Transform({
42419
42588
  transform(chunk, _enc, cb) {
@@ -42434,7 +42603,7 @@ async function downloadFile(opts) {
42434
42603
  return { bytes, sha256: sha2563, cached: false, elapsedMs: Date.now() - start };
42435
42604
  }
42436
42605
  async function hashFile(filePath) {
42437
- const hasher = createHash("sha256");
42606
+ const hasher = createHash2("sha256");
42438
42607
  const handle = await fs2.open(filePath, "r");
42439
42608
  try {
42440
42609
  const stream = handle.createReadStream();