@canonry/canonry 5.13.0 → 5.14.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.
@@ -133,7 +133,7 @@ import {
133
133
  upgradeCaveatFor,
134
134
  upgradeCommandFor,
135
135
  visibilityReportRequestSchema
136
- } from "./chunk-UWJAATGC.js";
136
+ } from "./chunk-45EGDRVF.js";
137
137
 
138
138
  // src/cli-error.ts
139
139
  function isMachineFormat(format) {
@@ -12143,6 +12143,33 @@ function categorizeSourceWithCompetitors(uri, competitorDomains, isCompetitorMat
12143
12143
  }
12144
12144
  return base;
12145
12145
  }
12146
+ var LISTING_MARKETPLACE_DOMAINS = [
12147
+ "apartmentfinder.com",
12148
+ "apartmentguide.com",
12149
+ "apartmenthomeliving.com",
12150
+ "apartmentlist.com",
12151
+ "apartmentratings.com",
12152
+ "apartments.com",
12153
+ "craigslist.org",
12154
+ "forrent.com",
12155
+ "homes.com",
12156
+ "hotpads.com",
12157
+ "padmapper.com",
12158
+ "realtor.com",
12159
+ "redfin.com",
12160
+ "rent.com",
12161
+ "rentable.co",
12162
+ "rentals.com",
12163
+ "rentcafe.com",
12164
+ "student.com",
12165
+ "trulia.com",
12166
+ "zillow.com",
12167
+ "zumper.com"
12168
+ ];
12169
+ function isListingMarketplace(domainOrUri) {
12170
+ const domain = hostOf(domainOrUri) ?? domainOrUri.trim().toLowerCase();
12171
+ return LISTING_MARKETPLACE_DOMAINS.some((marketplace) => hostMatchesDomain(domain, marketplace));
12172
+ }
12146
12173
  function categoryLabel(category) {
12147
12174
  return CATEGORY_LABELS[category];
12148
12175
  }
@@ -19739,6 +19766,7 @@ export {
19739
19766
  shareOfVoiceSummary,
19740
19767
  categorizeSource,
19741
19768
  categorizeSourceWithCompetitors,
19769
+ isListingMarketplace,
19742
19770
  categoryLabel,
19743
19771
  cosineSimilarity,
19744
19772
  clusterByCosine,
@@ -5,12 +5,12 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-Q35D2R2P.js";
8
+ } from "./chunk-RGMUT5KY.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
12
12
  TEMPLATE_LINK_RATIO_THRESHOLD
13
- } from "./chunk-UWJAATGC.js";
13
+ } from "./chunk-45EGDRVF.js";
14
14
 
15
15
  // src/site-crawl-graph-layout.ts
16
16
  import crypto from "crypto";
@@ -404,6 +404,7 @@ import {
404
404
  internalError,
405
405
  intersectScopes,
406
406
  isBrowserProvider,
407
+ isListingMarketplace,
407
408
  isLocationRedirectStatus,
408
409
  isReadOnlyKey,
409
410
  isRetryableHttpError,
@@ -783,10 +784,10 @@ import {
783
784
  wordpressSchemaDeployResultDtoSchema,
784
785
  wordpressSchemaStatusResultDtoSchema,
785
786
  wordpressStatusDtoSchema
786
- } from "./chunk-UWJAATGC.js";
787
+ } from "./chunk-45EGDRVF.js";
787
788
 
788
789
  // src/intelligence-service.ts
789
- import { eq as eq70, desc as desc32, asc as asc12, and as and60, ne as ne11, or as or18, inArray as inArray27, gte as gte18, lte as lte15, isNull as isNull13, sql as sql28, exists } from "drizzle-orm";
790
+ import { eq as eq71, desc as desc32, asc as asc12, and as and60, ne as ne11, or as or18, inArray as inArray27, gte as gte18, lte as lte15, isNull as isNull13, sql as sql28, exists } from "drizzle-orm";
790
791
 
791
792
  // ../db/src/client.ts
792
793
  import { mkdirSync } from "fs";
@@ -19691,12 +19692,12 @@ function upsertCompetitor(authoring, body) {
19691
19692
  };
19692
19693
  }
19693
19694
  function removeCompetitor(authoring, body) {
19694
- const { groupKey, competitorKey } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
19695
+ const { groupKey, competitorKey: competitorKey2 } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
19695
19696
  requireGroup(authoring, groupKey);
19696
19697
  return {
19697
19698
  authoring: {
19698
19699
  ...authoring,
19699
- groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !== competitorKey) } : group)
19700
+ groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !== competitorKey2) } : group)
19700
19701
  },
19701
19702
  warnings: []
19702
19703
  };
@@ -85596,9 +85597,57 @@ function utcDayBounds(now) {
85596
85597
  return { start, end, date };
85597
85598
  }
85598
85599
 
85600
+ // ../api-routes/src/plan-competitors.ts
85601
+ import { eq as eq69 } from "drizzle-orm";
85602
+ function competitorKey(value) {
85603
+ const host = hostOf(value) ?? value.trim().toLowerCase();
85604
+ return registrableDomain(host) ?? host;
85605
+ }
85606
+ function measurementPlanCompetitors(db, versionId) {
85607
+ if (!versionId) return [];
85608
+ const row = db.select({ canonicalJson: measurementPlanVersions.canonicalJson }).from(measurementPlanVersions).where(eq69(measurementPlanVersions.id, versionId)).get();
85609
+ if (!row) return [];
85610
+ let raw;
85611
+ try {
85612
+ const plan = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
85613
+ raw = plan.schemaVersion === MEASUREMENT_PLAN_V2_SCHEMA_VERSION ? plan.groups.flatMap((group) => group.competitors.map((competitor) => ({ domain: competitor.domain, names: [competitor.label, ...competitor.aliases] }))) : plan.groups.flatMap((group) => (group.competitors ?? []).map((domain) => ({ domain, names: [] })));
85614
+ } catch {
85615
+ return [];
85616
+ }
85617
+ const merged = /* @__PURE__ */ new Map();
85618
+ for (const { domain, names } of raw) {
85619
+ const key = competitorKey(domain);
85620
+ if (!key) continue;
85621
+ const set = merged.get(key) ?? /* @__PURE__ */ new Set();
85622
+ for (const name of names) if (name.trim()) set.add(name.trim());
85623
+ merged.set(key, set);
85624
+ }
85625
+ return [...merged].sort(([left], [right]) => left.localeCompare(right)).map(([domain, names]) => ({ domain, aliases: [...names] }));
85626
+ }
85627
+ function createRunCompetitorResolver(db, projectCompetitorDomains) {
85628
+ const byVersion = /* @__PURE__ */ new Map();
85629
+ const listOnly = () => ({ domains: [...new Set(projectCompetitorDomains)], aliases: /* @__PURE__ */ new Map() });
85630
+ return (versionId) => {
85631
+ if (!versionId) return listOnly();
85632
+ const cached = byVersion.get(versionId);
85633
+ if (cached) return cached;
85634
+ const domains = /* @__PURE__ */ new Map();
85635
+ for (const domain of projectCompetitorDomains) domains.set(competitorKey(domain), domain);
85636
+ const aliases = /* @__PURE__ */ new Map();
85637
+ for (const competitor of measurementPlanCompetitors(db, versionId)) {
85638
+ const domain = domains.get(competitor.domain) ?? competitor.domain;
85639
+ domains.set(competitor.domain, domain);
85640
+ if (competitor.aliases.length) aliases.set(domain, competitor.aliases);
85641
+ }
85642
+ const resolved = { domains: [...new Set(domains.values())], aliases };
85643
+ byVersion.set(versionId, resolved);
85644
+ return resolved;
85645
+ };
85646
+ }
85647
+
85599
85648
  // ../api-routes/src/simple-measurement-definitions.ts
85600
85649
  import crypto51 from "crypto";
85601
- import { and as and59, eq as eq69 } from "drizzle-orm";
85650
+ import { and as and59, eq as eq70 } from "drizzle-orm";
85602
85651
  function captureSimpleMeasurementDefinition(db, input) {
85603
85652
  return db.transaction((tx) => {
85604
85653
  const run = tx.select({
@@ -85606,7 +85655,7 @@ function captureSimpleMeasurementDefinition(db, input) {
85606
85655
  trigger: runs.trigger,
85607
85656
  status: runs.status,
85608
85657
  measurementPlanVersionId: runs.measurementPlanVersionId
85609
- }).from(runs).where(and59(eq69(runs.projectId, input.projectId), eq69(runs.id, input.runId))).get();
85658
+ }).from(runs).where(and59(eq70(runs.projectId, input.projectId), eq70(runs.id, input.runId))).get();
85610
85659
  if (!run) throw notFound("Run", input.runId);
85611
85660
  if (run.kind !== RunKinds["answer-visibility"] || run.trigger === RunTriggers.probe || run.measurementPlanVersionId !== null) {
85612
85661
  return null;
@@ -85616,7 +85665,7 @@ function captureSimpleMeasurementDefinition(db, input) {
85616
85665
  if (definition.queries.some((query) => query.queryClass !== (classifier?.classify(query.queryText) ?? null))) {
85617
85666
  throw validationError("Query classes must match the captured identity and text.");
85618
85667
  }
85619
- const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(eq69(simpleMeasurementDefinitions.projectId, input.projectId), eq69(simpleMeasurementDefinitions.runId, input.runId))).get();
85668
+ const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(eq70(simpleMeasurementDefinitions.projectId, input.projectId), eq70(simpleMeasurementDefinitions.runId, input.runId))).get();
85620
85669
  if (existing) {
85621
85670
  const frozen = simpleMeasurementDefinitionSchema.parse(existing.definition);
85622
85671
  const replayDefinition = {
@@ -85637,15 +85686,15 @@ function captureSimpleMeasurementDefinition(db, input) {
85637
85686
  if (run.status !== RunStatuses.running) {
85638
85687
  throw validationError("Only a running run can capture a new measurement definition.");
85639
85688
  }
85640
- if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq69(querySnapshots.runId, input.runId)).limit(1).get()) {
85689
+ if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq70(querySnapshots.runId, input.runId)).limit(1).get()) {
85641
85690
  throw validationError("This run already has stored answers. Its measurement definition cannot be inferred afterward.");
85642
85691
  }
85643
- const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq69(queries.projectId, input.projectId)).all().map((query) => query.id));
85692
+ const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq70(queries.projectId, input.projectId)).all().map((query) => query.id));
85644
85693
  if (definition.queries.some((query) => !projectQueryIds.has(query.queryId))) {
85645
85694
  throw validationError("Every captured query must belong to the run project.");
85646
85695
  }
85647
85696
  if (definition.competitors !== void 0) {
85648
- const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(eq69(competitors.projectId, input.projectId)).all().map((competitor) => competitor.domain));
85697
+ const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(eq70(competitors.projectId, input.projectId)).all().map((competitor) => competitor.domain));
85649
85698
  const capturedDomains = new Set(definition.competitors.map((competitor) => competitor.domain));
85650
85699
  if (liveCompetitorDomains.size !== capturedDomains.size || [...liveCompetitorDomains].some((domain) => !capturedDomains.has(domain))) {
85651
85700
  throw validationError("Captured competitors must exactly match the project competitors dispatched for this run.");
@@ -86462,7 +86511,7 @@ function determineCitationState(normalized, domains) {
86462
86511
  }
86463
86512
  return "not-cited";
86464
86513
  }
86465
- function computeCompetitorOverlap(normalized, competitorDomains) {
86514
+ function computeCompetitorOverlap(normalized, competitorDomains, competitorAliases = /* @__PURE__ */ new Map()) {
86466
86515
  const overlapSet = /* @__PURE__ */ new Set();
86467
86516
  for (const d of normalized.citedDomains) {
86468
86517
  for (const cd of competitorDomains) {
@@ -86487,6 +86536,10 @@ function computeCompetitorOverlap(normalized, competitorDomains) {
86487
86536
  if (brandKeyFromText(brand).length >= 4 && textContainsBrandAlias(normalized.answerText, brand)) {
86488
86537
  overlapSet.add(cd);
86489
86538
  }
86539
+ const named = competitorAliases.get(cd);
86540
+ if (named?.length && textContainsAnyBrandAlias(normalized.answerText, named)) {
86541
+ overlapSet.add(cd);
86542
+ }
86490
86543
  }
86491
86544
  }
86492
86545
  return [...overlapSet];
@@ -86500,7 +86553,7 @@ function computeCitedCompetitorDomains(citedDomains, competitorDomains) {
86500
86553
  }
86501
86554
  return [...citedCompetitors];
86502
86555
  }
86503
- function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = []) {
86556
+ function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = [], competitorAliases = /* @__PURE__ */ new Map()) {
86504
86557
  if (!answerText || answerText.length < 20) return [];
86505
86558
  const ownBrandAliases = new Set(
86506
86559
  ownDomains.flatMap((domain) => collectBrandAliasesFromDomain(domain))
@@ -86510,7 +86563,7 @@ function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, com
86510
86563
  }
86511
86564
  const ownKeys = new Set([...ownBrandAliases].map(brandKeyFromText));
86512
86565
  const knownCompetitorAliases = new Set(
86513
- [...citedDomains, ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
86566
+ [...citedDomains.filter((domain) => !isListingMarketplace(domain)), ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).concat([...competitorAliases.values()].flat()).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
86514
86567
  );
86515
86568
  if (knownCompetitorAliases.size === 0) return [];
86516
86569
  const candidatePatterns = [
@@ -86592,10 +86645,10 @@ var log = createLogger("IntelligenceService");
86592
86645
  var runChronologyKey = sql28`coalesce(${runs.finishedAt}, ${runs.createdAt})`;
86593
86646
  function analyzableRunPredicates(projectId) {
86594
86647
  return [
86595
- eq70(runs.projectId, projectId),
86648
+ eq71(runs.projectId, projectId),
86596
86649
  // Only this kind writes query_snapshots.
86597
- eq70(runs.kind, RunKinds["answer-visibility"]),
86598
- or18(eq70(runs.status, RunStatuses.completed), eq70(runs.status, RunStatuses.partial)),
86650
+ eq71(runs.kind, RunKinds["answer-visibility"]),
86651
+ or18(eq71(runs.status, RunStatuses.completed), eq71(runs.status, RunStatuses.partial)),
86599
86652
  // Defensive: RunCoordinator already skips probes before analyzeAndPersist
86600
86653
  // is called, but a future call site invoking it directly for a probe must
86601
86654
  // still not pollute the intelligence window.
@@ -86640,7 +86693,7 @@ var IntelligenceService = class {
86640
86693
  * Returns the analysis result for the coordinator to inspect (e.g. for webhook dispatch).
86641
86694
  */
86642
86695
  analyzeAndPersist(runId, projectId) {
86643
- const currentRunRecord = this.db.select().from(runs).where(and60(eq70(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
86696
+ const currentRunRecord = this.db.select().from(runs).where(and60(eq71(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
86644
86697
  if (!currentRunRecord) {
86645
86698
  log.info("intelligence.skip", { runId, reason: "run not eligible for analysis" });
86646
86699
  return null;
@@ -86649,7 +86702,7 @@ var IntelligenceService = class {
86649
86702
  const recentRuns = this.db.select().from(runs).where(
86650
86703
  and60(
86651
86704
  ...analyzableRunPredicates(projectId),
86652
- currentLocation === null ? isNull13(runs.location) : eq70(runs.location, currentLocation),
86705
+ currentLocation === null ? isNull13(runs.location) : eq71(runs.location, currentLocation),
86653
86706
  // Never look forward. The window is this run's own past, so
86654
86707
  // re-analyzing a historical run compares it against its true
86655
86708
  // predecessor rather than against sweeps that came after it.
@@ -86657,7 +86710,7 @@ var IntelligenceService = class {
86657
86710
  // MEASUREMENT: only runs that actually wrote snapshots — see above.
86658
86711
  // Index seek on idx_snapshots_run, short-circuited on the first row.
86659
86712
  exists(
86660
- this.db.select({ one: sql28`1` }).from(querySnapshots).where(eq70(querySnapshots.runId, runs.id))
86713
+ this.db.select({ one: sql28`1` }).from(querySnapshots).where(eq71(querySnapshots.runId, runs.id))
86661
86714
  )
86662
86715
  )
86663
86716
  ).orderBy(desc32(runs.finishedAt), desc32(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
@@ -86732,7 +86785,7 @@ var IntelligenceService = class {
86732
86785
  * Returns the persisted insights so the coordinator can count critical/high.
86733
86786
  */
86734
86787
  analyzeAndPersistGbp(runId, projectId) {
86735
- const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq70(runs.id, runId)).get();
86788
+ const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq71(runs.id, runId)).get();
86736
86789
  if (!runRow) {
86737
86790
  log.info("gbp-intelligence.skip", { runId, reason: "run not found" });
86738
86791
  this.persistGbpInsights(runId, projectId, [], []);
@@ -86741,8 +86794,8 @@ var IntelligenceService = class {
86741
86794
  const windowStart = runRow.startedAt ?? runRow.createdAt;
86742
86795
  const windowEnd = runRow.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString();
86743
86796
  const selected = this.db.select().from(gbpLocations).where(and60(
86744
- eq70(gbpLocations.projectId, projectId),
86745
- eq70(gbpLocations.selected, true),
86797
+ eq71(gbpLocations.projectId, projectId),
86798
+ eq71(gbpLocations.selected, true),
86746
86799
  gte18(gbpLocations.syncedAt, windowStart),
86747
86800
  lte15(gbpLocations.syncedAt, windowEnd)
86748
86801
  )).all();
@@ -86777,12 +86830,12 @@ var IntelligenceService = class {
86777
86830
  }
86778
86831
  /** Build the per-location signal bundle the GBP analyzer consumes. */
86779
86832
  buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
86780
- const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and60(eq70(gbpDailyMetrics.projectId, projectId), eq70(gbpDailyMetrics.locationName, locationName))).all();
86781
- const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and60(eq70(gbpPlaceActions.projectId, projectId), eq70(gbpPlaceActions.locationName, locationName))).all();
86782
- const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and60(eq70(gbpLodgingSnapshots.projectId, projectId), eq70(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc32(gbpLodgingSnapshots.syncedAt)).limit(1).get();
86783
- const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and60(eq70(gbpLocations.projectId, projectId), eq70(gbpLocations.locationName, locationName))).get();
86833
+ const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and60(eq71(gbpDailyMetrics.projectId, projectId), eq71(gbpDailyMetrics.locationName, locationName))).all();
86834
+ const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and60(eq71(gbpPlaceActions.projectId, projectId), eq71(gbpPlaceActions.locationName, locationName))).all();
86835
+ const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and60(eq71(gbpLodgingSnapshots.projectId, projectId), eq71(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc32(gbpLodgingSnapshots.syncedAt)).limit(1).get();
86836
+ const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and60(eq71(gbpLocations.projectId, projectId), eq71(gbpLocations.locationName, locationName))).get();
86784
86837
  const descriptionMissing = !(ownerRow?.description ?? "").trim();
86785
- const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and60(eq70(gbpPlaceDetails.projectId, projectId), eq70(gbpPlaceDetails.locationName, locationName))).orderBy(desc32(gbpPlaceDetails.syncedAt)).limit(1).get();
86838
+ const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and60(eq71(gbpPlaceDetails.projectId, projectId), eq71(gbpPlaceDetails.locationName, locationName))).orderBy(desc32(gbpPlaceDetails.syncedAt)).limit(1).get();
86786
86839
  const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
86787
86840
  const summary3 = buildGbpSummary({
86788
86841
  locationName,
@@ -86818,7 +86871,7 @@ var IntelligenceService = class {
86818
86871
  /** Build the month-over-month keyword series for a location from the
86819
86872
  * accumulating gbp_keyword_monthly table (latest complete month vs prior). */
86820
86873
  buildGbpKeywordTrend(projectId, locationName) {
86821
- const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and60(eq70(gbpKeywordMonthly.projectId, projectId), eq70(gbpKeywordMonthly.locationName, locationName))).all();
86874
+ const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and60(eq71(gbpKeywordMonthly.projectId, projectId), eq71(gbpKeywordMonthly.locationName, locationName))).all();
86822
86875
  if (rows.length === 0) return { recentMonth: null, priorMonth: null, points: [] };
86823
86876
  const months = [...new Set(rows.map((r) => r.month))].sort().reverse();
86824
86877
  const recentMonth = months[0] ?? null;
@@ -86849,7 +86902,7 @@ var IntelligenceService = class {
86849
86902
  */
86850
86903
  persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
86851
86904
  const covered = new Set(coveredLocationNames);
86852
- const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and60(eq70(insights.projectId, projectId), eq70(insights.provider, GBP_INSIGHT_PROVIDER))).all();
86905
+ const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and60(eq71(insights.projectId, projectId), eq71(insights.provider, GBP_INSIGHT_PROVIDER))).all();
86853
86906
  const staleIds = [];
86854
86907
  const dismissedSlots = /* @__PURE__ */ new Set();
86855
86908
  for (const row of existing) {
@@ -86860,7 +86913,7 @@ var IntelligenceService = class {
86860
86913
  }
86861
86914
  this.db.transaction((tx) => {
86862
86915
  for (const id of staleIds) {
86863
- tx.delete(insights).where(eq70(insights.id, id)).run();
86916
+ tx.delete(insights).where(eq71(insights.id, id)).run();
86864
86917
  }
86865
86918
  for (const insight of gbpInsights) {
86866
86919
  const parsed = parseGbpInsightId(insight.id);
@@ -86946,7 +86999,7 @@ var IntelligenceService = class {
86946
86999
  * create per run + aggregate). DB is left untouched.
86947
87000
  */
86948
87001
  backfill(projectName, opts, onProgress) {
86949
- const project = this.db.select().from(projects).where(eq70(projects.name, projectName)).get();
87002
+ const project = this.db.select().from(projects).where(eq71(projects.name, projectName)).get();
86950
87003
  if (!project) {
86951
87004
  throw new Error(`Project "${projectName}" not found`);
86952
87005
  }
@@ -87035,7 +87088,7 @@ var IntelligenceService = class {
87035
87088
  return { processed, skipped: skipped3, totalInsights };
87036
87089
  }
87037
87090
  loadTrackedCompetitors(projectId) {
87038
- return this.db.select({ domain: competitors.domain }).from(competitors).where(eq70(competitors.projectId, projectId)).all().map((r) => r.domain);
87091
+ return this.db.select({ domain: competitors.domain }).from(competitors).where(eq71(competitors.projectId, projectId)).all().map((r) => r.domain);
87039
87092
  }
87040
87093
  /**
87041
87094
  * Which of `runIds` actually wrote query snapshots. One grouped read, so
@@ -87066,15 +87119,15 @@ var IntelligenceService = class {
87066
87119
  }
87067
87120
  persistResult(result, runId, projectId) {
87068
87121
  const previouslyDismissed = /* @__PURE__ */ new Set();
87069
- const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(eq70(insights.runId, runId)).all();
87122
+ const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(eq71(insights.runId, runId)).all();
87070
87123
  for (const row of existingInsights) {
87071
87124
  if (row.dismissed) {
87072
87125
  previouslyDismissed.add(`${row.query}:${row.provider}:${row.type}`);
87073
87126
  }
87074
87127
  }
87075
87128
  this.db.transaction((tx) => {
87076
- tx.delete(insights).where(eq70(insights.runId, runId)).run();
87077
- tx.delete(healthSnapshots).where(eq70(healthSnapshots.runId, runId)).run();
87129
+ tx.delete(insights).where(eq71(insights.runId, runId)).run();
87130
+ tx.delete(healthSnapshots).where(eq71(healthSnapshots.runId, runId)).run();
87078
87131
  const now = (/* @__PURE__ */ new Date()).toISOString();
87079
87132
  for (const insight of result.insights) {
87080
87133
  const wasDismissed = previouslyDismissed.has(`${insight.query}:${insight.provider}:${insight.type}`);
@@ -87122,7 +87175,7 @@ var IntelligenceService = class {
87122
87175
  impressions: gscSearchData.impressions,
87123
87176
  position: gscSearchData.position
87124
87177
  }).from(gscSearchData).where(and60(
87125
- eq70(gscSearchData.projectId, projectId),
87178
+ eq71(gscSearchData.projectId, projectId),
87126
87179
  gte18(gscSearchData.date, window.startDate),
87127
87180
  lte15(gscSearchData.date, window.endDate)
87128
87181
  )).all();
@@ -87175,7 +87228,7 @@ var IntelligenceService = class {
87175
87228
  const key = row.query.toLowerCase();
87176
87229
  gscImpressionsByQuery.set(key, (gscImpressionsByQuery.get(key) ?? 0) + row.impressions);
87177
87230
  }
87178
- const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq70(projects.id, projectId)).get();
87231
+ const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq71(projects.id, projectId)).get();
87179
87232
  const locationCount = Math.max(
87180
87233
  1,
87181
87234
  (projectRow?.locations ?? []).length
@@ -87183,9 +87236,9 @@ var IntelligenceService = class {
87183
87236
  const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
87184
87237
  const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
87185
87238
  and60(
87186
- eq70(runs.projectId, projectId),
87187
- eq70(runs.kind, RunKinds["answer-visibility"]),
87188
- or18(eq70(runs.status, "completed"), eq70(runs.status, "partial")),
87239
+ eq71(runs.projectId, projectId),
87240
+ eq71(runs.kind, RunKinds["answer-visibility"]),
87241
+ or18(eq71(runs.status, "completed"), eq71(runs.status, "partial")),
87189
87242
  // Defensive — see top of file.
87190
87243
  ne11(runs.trigger, RunTriggers.probe)
87191
87244
  )
@@ -87205,7 +87258,7 @@ var IntelligenceService = class {
87205
87258
  const haveHistory = recentRunIds.length > 0;
87206
87259
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
87207
87260
  if (haveHistory) {
87208
- const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and60(eq70(insights.type, "regression"), inArray27(insights.runId, recentRunIds))).all();
87261
+ const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and60(eq71(insights.type, "regression"), inArray27(insights.runId, recentRunIds))).all();
87209
87262
  const regressionGroups = /* @__PURE__ */ new Map();
87210
87263
  for (const row of priorRows) {
87211
87264
  if (!row.runId) continue;
@@ -87234,7 +87287,7 @@ var IntelligenceService = class {
87234
87287
  });
87235
87288
  }
87236
87289
  buildRunData(runId, projectId, completedAt, location = null, trackedCompetitors = []) {
87237
- const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(eq70(projects.id, projectId)).get();
87290
+ const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(eq71(projects.id, projectId)).get();
87238
87291
  const projectDomains = projectDomainRow ? effectiveDomains({
87239
87292
  canonicalDomain: projectDomainRow.canonicalDomain,
87240
87293
  ownedDomains: projectDomainRow.ownedDomains
@@ -87252,7 +87305,7 @@ var IntelligenceService = class {
87252
87305
  citedDomains: querySnapshots.citedDomains,
87253
87306
  rawResponse: querySnapshots.rawResponse,
87254
87307
  snapshotLocation: querySnapshots.location
87255
- }).from(querySnapshots).leftJoin(queries, eq70(querySnapshots.queryId, queries.id)).where(eq70(querySnapshots.runId, runId)).all();
87308
+ }).from(querySnapshots).leftJoin(queries, eq71(querySnapshots.queryId, queries.id)).where(eq71(querySnapshots.runId, runId)).all();
87256
87309
  const snapshots = [];
87257
87310
  let orphanCount = 0;
87258
87311
  for (const r of rows) {
@@ -87473,6 +87526,7 @@ export {
87473
87526
  runChecks,
87474
87527
  executeDiscovery,
87475
87528
  markSessionFailed,
87529
+ createRunCompetitorResolver,
87476
87530
  captureSimpleMeasurementDefinition,
87477
87531
  apiRoutes,
87478
87532
  addLogListener,
@@ -17,12 +17,12 @@ import {
17
17
  resolveOperatorApiKeyIds,
18
18
  runWithUsageTags,
19
19
  saveConfigPatch
20
- } from "./chunk-IPGBK7XR.js";
20
+ } from "./chunk-2W6GCJ3O.js";
21
21
  import {
22
22
  deleteSiteCrawlGraphLayout,
23
23
  persistSiteCrawlGraphLayout,
24
24
  prepareSiteCrawlGraphLayout
25
- } from "./chunk-IDZQ5H3J.js";
25
+ } from "./chunk-4LPV6ZZY.js";
26
26
  import {
27
27
  PACKAGE_VERSION
28
28
  } from "./chunk-AOJU5LKX.js";
@@ -73,6 +73,7 @@ import {
73
73
  createCredentialChecker,
74
74
  createFastifyLogger,
75
75
  createLogger,
76
+ createRunCompetitorResolver,
76
77
  createUserSession,
77
78
  deliverWebhook,
78
79
  determineCitationState,
@@ -183,7 +184,7 @@ import {
183
184
  siteLivenessState,
184
185
  toAlertView,
185
186
  usageCounters
186
- } from "./chunk-Q35D2R2P.js";
187
+ } from "./chunk-RGMUT5KY.js";
187
188
  import {
188
189
  AGENT_MEMORY_VALUE_MAX_BYTES,
189
190
  AGENT_NONE,
@@ -344,7 +345,7 @@ import {
344
345
  visibilityReportRequestSchema,
345
346
  winnabilityClassLabel,
346
347
  withRetry
347
- } from "./chunk-UWJAATGC.js";
348
+ } from "./chunk-45EGDRVF.js";
348
349
 
349
350
  // src/runtime-context.ts
350
351
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -6490,7 +6491,7 @@ function nonBlank(value) {
6490
6491
  return trimmed ? trimmed : void 0;
6491
6492
  }
6492
6493
  function resolveBuildCommit(env = process.env) {
6493
- const embedded = true ? "894086f6a60be75c0ade892884adf57ef7a38291" : void 0;
6494
+ const embedded = true ? "f4648ef75d44ebb5a3396cf05739a56a4aa2b7ee" : void 0;
6494
6495
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
6495
6496
  }
6496
6497
  function resolveInstanceIdentity(env = process.env) {
@@ -6965,7 +6966,8 @@ var JobRunner = class {
6965
6966
  }
6966
6967
  log2.info("run.dispatch", { runId, providerCount: activeProviders.length, providers: activeProviders.map((p) => p.adapter.name) });
6967
6968
  const projectCompetitors = this.db.select().from(competitors).where(eq2(competitors.projectId, projectId)).all();
6968
- const competitorDomains = projectCompetitors.map((c) => c.domain);
6969
+ const runCompetitors = createRunCompetitorResolver(this.db, projectCompetitors.map((c) => c.domain))(existingRun.measurementPlanVersionId);
6970
+ const competitorDomains = runCompetitors.domains;
6969
6971
  const allDomains = effectiveDomains({
6970
6972
  canonicalDomain: project.canonicalDomain,
6971
6973
  ownedDomains: project.ownedDomains
@@ -7169,6 +7171,7 @@ var JobRunner = class {
7169
7171
  runId,
7170
7172
  allDomains,
7171
7173
  competitorDomains,
7174
+ competitorAliases: runCompetitors.aliases,
7172
7175
  allBrandNames,
7173
7176
  executionGates,
7174
7177
  providerDispatchCounts,
@@ -7426,7 +7429,8 @@ var JobRunner = class {
7426
7429
  else providerErrors.set(provider, `No ${provider} provider is configured on this instance, so its missing answers did not run.`);
7427
7430
  }
7428
7431
  const projectCompetitors = this.db.select().from(competitors).where(eq2(competitors.projectId, projectId)).all();
7429
- const competitorDomains = projectCompetitors.map((c) => c.domain);
7432
+ const runCompetitors = createRunCompetitorResolver(this.db, projectCompetitors.map((c) => c.domain))(run.measurementPlanVersionId);
7433
+ const competitorDomains = runCompetitors.domains;
7430
7434
  const allDomains = effectiveDomains({ canonicalDomain: project.canonicalDomain, ownedDomains: project.ownedDomains });
7431
7435
  const allBrandNames = effectiveBrandNames({ displayName: project.displayName, aliases: project.aliases });
7432
7436
  const todayPeriod = getCurrentUsageDay();
@@ -7481,6 +7485,7 @@ var JobRunner = class {
7481
7485
  runId,
7482
7486
  allDomains,
7483
7487
  competitorDomains,
7488
+ competitorAliases: runCompetitors.aliases,
7484
7489
  allBrandNames,
7485
7490
  executionGates,
7486
7491
  providerDispatchCounts,
@@ -7634,13 +7639,14 @@ var JobRunner = class {
7634
7639
  ctx.allBrandNames,
7635
7640
  ctx.allDomains
7636
7641
  );
7637
- const overlap = computeCompetitorOverlap(normalized, ctx.competitorDomains);
7642
+ const overlap = computeCompetitorOverlap(normalized, ctx.competitorDomains, ctx.competitorAliases);
7638
7643
  const extractedCompetitors = extractRecommendedCompetitors(
7639
7644
  normalized.answerText,
7640
7645
  ctx.allDomains,
7641
7646
  normalized.citedDomains,
7642
7647
  ctx.competitorDomains,
7643
- ctx.allBrandNames
7648
+ ctx.allBrandNames,
7649
+ ctx.competitorAliases
7644
7650
  );
7645
7651
  const snapshotId = crypto6.randomUUID();
7646
7652
  let screenshotRelPath = null;
@@ -11568,10 +11574,11 @@ async function backfillAnswerVisibilityCommand(opts) {
11568
11574
  let reparsed = 0;
11569
11575
  let providerErrors = 0;
11570
11576
  if (scopedProjects.length > 0) {
11571
- const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(and13(
11577
+ const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId, planVersionId: runs.measurementPlanVersionId }).from(runs).where(and13(
11572
11578
  eq15(runs.kind, RunKinds["answer-visibility"]),
11573
11579
  inArray6(runs.projectId, scopedProjects.map((project) => project.id))
11574
- )).all() : db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(eq15(runs.kind, RunKinds["answer-visibility"])).all();
11580
+ )).all() : db.select({ id: runs.id, projectId: runs.projectId, planVersionId: runs.measurementPlanVersionId }).from(runs).where(eq15(runs.kind, RunKinds["answer-visibility"])).all();
11581
+ const planVersionByRun = new Map(runRows.map((run) => [run.id, run.planVersionId]));
11575
11582
  const runIdsByProject = /* @__PURE__ */ new Map();
11576
11583
  for (const run of runRows) {
11577
11584
  const existing = runIdsByProject.get(run.projectId);
@@ -11580,6 +11587,7 @@ async function backfillAnswerVisibilityCommand(opts) {
11580
11587
  }
11581
11588
  for (const project of scopedProjects) {
11582
11589
  const competitorDomains = db.select({ domain: competitors.domain }).from(competitors).where(eq15(competitors.projectId, project.id)).all().map((row) => row.domain);
11590
+ const competitorsForRun = createRunCompetitorResolver(db, competitorDomains);
11583
11591
  const runIds = runIdsByProject.get(project.id) ?? [];
11584
11592
  if (runIds.length === 0) continue;
11585
11593
  const projectDomains = effectiveDomains({
@@ -11594,6 +11602,7 @@ async function backfillAnswerVisibilityCommand(opts) {
11594
11602
  const batchRunIds = runIds.slice(offset, offset + SNAPSHOT_BATCH_SIZE);
11595
11603
  const snapshotRows = db.select({
11596
11604
  id: querySnapshots.id,
11605
+ runId: querySnapshots.runId,
11597
11606
  provider: querySnapshots.provider,
11598
11607
  citationState: querySnapshots.citationState,
11599
11608
  answerMentioned: querySnapshots.answerMentioned,
@@ -11634,13 +11643,15 @@ async function backfillAnswerVisibilityCommand(opts) {
11634
11643
  };
11635
11644
  const nextCitationState = determineCitationState(normalized, projectDomains);
11636
11645
  const nextCitedDomains = reparsedResult.citedDomains;
11637
- const nextCompetitorOverlap = computeCompetitorOverlap(normalized, competitorDomains);
11646
+ const runCompetitors = competitorsForRun(planVersionByRun.get(snapshot.runId));
11647
+ const nextCompetitorOverlap = computeCompetitorOverlap(normalized, runCompetitors.domains, runCompetitors.aliases);
11638
11648
  const nextRecommendedCompetitors = extractRecommendedCompetitors(
11639
11649
  normalized.answerText,
11640
11650
  projectDomains,
11641
11651
  normalized.citedDomains,
11642
- competitorDomains,
11643
- projectBrandNames
11652
+ runCompetitors.domains,
11653
+ projectBrandNames,
11654
+ runCompetitors.aliases
11644
11655
  );
11645
11656
  const nextRawResponse = stringifyStoredSnapshotEnvelope(
11646
11657
  snapshot.rawResponse,
@@ -11867,8 +11878,10 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
11867
11878
  const project = db.select().from(projects).where(eq15(projects.id, projectId)).get();
11868
11879
  if (!project) return { examined: 0, updated: 0, mentioned: 0 };
11869
11880
  const competitorDomains = db.select({ domain: competitors.domain }).from(competitors).where(eq15(competitors.projectId, projectId)).all().map((row) => row.domain);
11870
- const runRows = db.select({ id: runs.id }).from(runs).where(and13(eq15(runs.kind, RunKinds["answer-visibility"]), eq15(runs.projectId, projectId))).all();
11881
+ const runRows = db.select({ id: runs.id, planVersionId: runs.measurementPlanVersionId }).from(runs).where(and13(eq15(runs.kind, RunKinds["answer-visibility"]), eq15(runs.projectId, projectId))).all();
11871
11882
  const runIds = runRows.map((r) => r.id);
11883
+ const planVersionByRun = new Map(runRows.map((run) => [run.id, run.planVersionId]));
11884
+ const competitorsForRun = createRunCompetitorResolver(db, competitorDomains);
11872
11885
  let examined = 0;
11873
11886
  let updated = 0;
11874
11887
  let wouldUpdate = 0;
@@ -11888,6 +11901,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
11888
11901
  const batchRunIds = runIds.slice(offset, offset + SNAPSHOT_BATCH_SIZE);
11889
11902
  const snapshotRows = db.select({
11890
11903
  id: querySnapshots.id,
11904
+ runId: querySnapshots.runId,
11891
11905
  provider: querySnapshots.provider,
11892
11906
  answerMentioned: querySnapshots.answerMentioned,
11893
11907
  answerText: querySnapshots.answerText,
@@ -11913,13 +11927,15 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
11913
11927
  retrievalStatus: "unknown",
11914
11928
  searchQueries: []
11915
11929
  };
11916
- const nextCompetitorOverlap = computeCompetitorOverlap(normalized, competitorDomains);
11930
+ const runCompetitors = competitorsForRun(planVersionByRun.get(snapshot.runId));
11931
+ const nextCompetitorOverlap = computeCompetitorOverlap(normalized, runCompetitors.domains, runCompetitors.aliases);
11917
11932
  const nextRecommendedCompetitors = extractRecommendedCompetitors(
11918
11933
  answerText,
11919
11934
  projectDomains,
11920
11935
  citedDomains,
11921
- competitorDomains,
11922
- projectBrandNames
11936
+ runCompetitors.domains,
11937
+ projectBrandNames,
11938
+ runCompetitors.aliases
11923
11939
  );
11924
11940
  const nextPatch = {};
11925
11941
  if (snapshot.answerMentioned !== nextAnswerMentioned) {
@@ -12016,7 +12032,7 @@ function readStoredGroundingSources(rawResponse) {
12016
12032
  return result2;
12017
12033
  }
12018
12034
  async function backfillInsightsCommand(project, opts) {
12019
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-PM7MC5VC.js");
12035
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-CJKOXPOP.js");
12020
12036
  const config = loadConfig();
12021
12037
  const db = createClient(config.database);
12022
12038
  migrate(db);
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-IPGBK7XR.js";
7
+ } from "./chunk-2W6GCJ3O.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
10
  } from "./chunk-AOJU5LKX.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-UWJAATGC.js";
14
+ } from "./chunk-45EGDRVF.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -35,11 +35,11 @@ import {
35
35
  trackCliCommandFinished,
36
36
  trackEvent,
37
37
  waitForServerRuntimeStartup
38
- } from "./chunk-TDHRUXN3.js";
38
+ } from "./chunk-S6LJSUZO.js";
39
39
  import {
40
40
  autoSyncSkills,
41
41
  formatAutoSyncNotice
42
- } from "./chunk-6YLNO2T5.js";
42
+ } from "./chunk-SOLFOKZF.js";
43
43
  import {
44
44
  CliError,
45
45
  EXIT_SYSTEM_ERROR,
@@ -66,13 +66,13 @@ import {
66
66
  shouldPrintServeSkillsNudge,
67
67
  systemError,
68
68
  usageError
69
- } from "./chunk-IPGBK7XR.js";
69
+ } from "./chunk-2W6GCJ3O.js";
70
70
  import {
71
71
  DEFAULT_DEMO_TRUSTED_PROXIES,
72
72
  trustedProxiesProblem,
73
73
  trustedProxyProblem
74
74
  } from "./chunk-RB2F4D3Z.js";
75
- import "./chunk-IDZQ5H3J.js";
75
+ import "./chunk-4LPV6ZZY.js";
76
76
  import "./chunk-AOJU5LKX.js";
77
77
  import {
78
78
  CLOUDFLARE_WORKER_BINDINGS,
@@ -88,7 +88,7 @@ import {
88
88
  queries,
89
89
  renderReportHtml,
90
90
  runs
91
- } from "./chunk-Q35D2R2P.js";
91
+ } from "./chunk-RGMUT5KY.js";
92
92
  import {
93
93
  AdsDeliverySnapshotStatuses,
94
94
  AdsHistoricalCampaignRollupStatuses,
@@ -173,7 +173,7 @@ import {
173
173
  snapshotProviderModeSchema,
174
174
  visibilityReportRequestSchema,
175
175
  winnabilityClassSchema
176
- } from "./chunk-UWJAATGC.js";
176
+ } from "./chunk-45EGDRVF.js";
177
177
 
178
178
  // src/cli.ts
179
179
  import { pathToFileURL } from "url";
@@ -438,7 +438,7 @@ function parseDemoTrustedProxies(values) {
438
438
  async function demoCommand(options) {
439
439
  const { host, port } = parseDemoListenOptions(options);
440
440
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
441
- const { createDemoServer } = await import("./demo-server-IZFTJI7E.js");
441
+ const { createDemoServer } = await import("./demo-server-H4ZFIIIB.js");
442
442
  const app = await createDemoServer({ trustProxy });
443
443
  let stopping = false;
444
444
  const stop = () => {
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  layoutSiteCrawlGraphInput,
6
6
  persistSiteCrawlGraphLayout
7
- } from "./chunk-IDZQ5H3J.js";
7
+ } from "./chunk-4LPV6ZZY.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
10
  } from "./chunk-AOJU5LKX.js";
@@ -83,7 +83,7 @@ import {
83
83
  siteCrawlPages,
84
84
  siteCrawlSnapshots,
85
85
  trafficSources
86
- } from "./chunk-Q35D2R2P.js";
86
+ } from "./chunk-RGMUT5KY.js";
87
87
  import {
88
88
  RunKinds,
89
89
  SiteCrawlFetchStates,
@@ -104,7 +104,7 @@ import {
104
104
  measurementPlanV2Schema,
105
105
  placementLinkDecision,
106
106
  siteAuditPageFactorSchema
107
- } from "./chunk-UWJAATGC.js";
107
+ } from "./chunk-45EGDRVF.js";
108
108
 
109
109
  // src/demo-server.ts
110
110
  import { dirname, join as join2 } from "path";
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-TDHRUXN3.js";
6
+ } from "./chunk-S6LJSUZO.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-IPGBK7XR.js";
10
- import "./chunk-IDZQ5H3J.js";
9
+ } from "./chunk-2W6GCJ3O.js";
10
+ import "./chunk-4LPV6ZZY.js";
11
11
  import "./chunk-AOJU5LKX.js";
12
- import "./chunk-Q35D2R2P.js";
13
- import "./chunk-UWJAATGC.js";
12
+ import "./chunk-RGMUT5KY.js";
13
+ import "./chunk-45EGDRVF.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
16
16
  createGoogleMarketingCredentialStore,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-Q35D2R2P.js";
5
- import "./chunk-UWJAATGC.js";
4
+ } from "./chunk-RGMUT5KY.js";
5
+ import "./chunk-45EGDRVF.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
8
8
  IntelligenceService
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-6YLNO2T5.js";
3
+ } from "./chunk-SOLFOKZF.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-IPGBK7XR.js";
7
+ } from "./chunk-2W6GCJ3O.js";
8
8
  import "./chunk-AOJU5LKX.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-UWJAATGC.js";
12
+ } from "./chunk-45EGDRVF.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { randomUUID } from "crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "5.13.0",
3
+ "version": "5.14.0",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "keywords": [
@@ -95,23 +95,23 @@
95
95
  "@ainyc/canonry-integration-bing": "0.0.0",
96
96
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
97
97
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
98
- "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
99
98
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
100
- "@ainyc/canonry-integration-google": "0.0.0",
99
+ "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
101
100
  "@ainyc/canonry-integration-google-ads": "0.0.0",
101
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
102
+ "@ainyc/canonry-integration-google": "0.0.0",
102
103
  "@ainyc/canonry-integration-google-places": "0.0.0",
103
- "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
104
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
105
- "@ainyc/canonry-integration-wordpress": "0.0.0",
106
104
  "@ainyc/canonry-integration-traffic": "0.0.0",
105
+ "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
107
106
  "@ainyc/canonry-intelligence": "0.0.0",
108
107
  "@ainyc/canonry-provider-cdp": "0.0.0",
109
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
108
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
109
+ "@ainyc/canonry-provider-claude": "0.0.0",
110
110
  "@ainyc/canonry-provider-gemini": "0.0.0",
111
111
  "@ainyc/canonry-provider-local": "0.0.0",
112
- "@ainyc/canonry-provider-claude": "0.0.0",
113
- "@ainyc/canonry-provider-openai": "0.0.0",
114
- "@ainyc/canonry-provider-perplexity": "0.0.0"
112
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
113
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
114
+ "@ainyc/canonry-provider-openai": "0.0.0"
115
115
  },
116
116
  "scripts": {
117
117
  "build": "pnpm run build:cli && pnpm run build:web",