@canonry/canonry 5.13.0 → 5.15.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 (28) hide show
  1. package/assets/assets/{AuditHistoryPanel-DWDOPf8c.js → AuditHistoryPanel-BZJn-wvp.js} +1 -1
  2. package/assets/assets/{BacklinksPage-DGxq-iU6.js → BacklinksPage-DsQAKO31.js} +1 -1
  3. package/assets/assets/{HistoryPage-DR91m-gT.js → HistoryPage-DWn459Gu.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-a8poltfM.js → MeasurementPropertyPage-D6pUcBiT.js} +1 -1
  5. package/assets/assets/{ProjectPage-CCCJE7rA.js → ProjectPage-D-lDBpPV.js} +1 -1
  6. package/assets/assets/{RunRow-Xe63DyPK.js → RunRow-BJxx50Ar.js} +1 -1
  7. package/assets/assets/{RunsPage-DK119ZZw.js → RunsPage-DvoNDx6z.js} +1 -1
  8. package/assets/assets/{SettingsPage-G461foD-.js → SettingsPage-DXbhM5Lv.js} +1 -1
  9. package/assets/assets/{SiteHealthSection-CJnHkGM2.js → SiteHealthSection-4mMfc6Rb.js} +3 -3
  10. package/assets/assets/{TrafficPage-AsWgc7Ot.js → TrafficPage-EYSxLxkQ.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-D10yBQoD.js → TrafficSourceDetailPage-DY4sV_BX.js} +1 -1
  12. package/assets/assets/{extract-error-message-PP4HD_Dp.js → extract-error-message-BMpWRqf9.js} +1 -1
  13. package/assets/assets/{index-CCIeAE4J.js → index-KCAlcuMN.js} +22 -22
  14. package/assets/assets/{react-sigma_core.esm.min-CkyyYkKU.js → react-sigma_core.esm.min-CHepSGqZ.js} +1 -1
  15. package/assets/assets/{v2-overview-adapter-DW-In1hp.js → v2-overview-adapter-CpM-FjB_.js} +1 -1
  16. package/assets/index.html +1 -1
  17. package/dist/{chunk-Q35D2R2P.js → chunk-3YAPVVFN.js} +173 -52
  18. package/dist/{chunk-IDZQ5H3J.js → chunk-CDQDPUY4.js} +2 -2
  19. package/dist/{chunk-6YLNO2T5.js → chunk-JO5HHEJV.js} +2 -2
  20. package/dist/{chunk-UWJAATGC.js → chunk-L36TC6LB.js} +90 -7
  21. package/dist/{chunk-TDHRUXN3.js → chunk-SJ7ZOFL5.js} +92 -31
  22. package/dist/{chunk-IPGBK7XR.js → chunk-ZGZSROSR.js} +1 -1
  23. package/dist/cli.js +7 -7
  24. package/dist/{demo-server-IZFTJI7E.js → demo-server-QLQUVMKJ.js} +3 -3
  25. package/dist/index.js +5 -5
  26. package/dist/{intelligence-service-PM7MC5VC.js → intelligence-service-EAUKUVVM.js} +2 -2
  27. package/dist/mcp.js +3 -3
  28. package/package.json +7 -7
@@ -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-L36TC6LB.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";
@@ -3296,6 +3297,7 @@ var adsCampaigns = sqliteTable("ads_campaigns", {
3296
3297
  lifetimeSpendLimitMicros: integer("lifetime_spend_limit_micros"),
3297
3298
  conversionEventSettingIds: text("conversion_event_setting_ids", { mode: "json" }).$type().notNull().default([]),
3298
3299
  targeting: text("targeting", { mode: "json" }).$type(),
3300
+ landingPageQueryStringTemplate: text("landing_page_query_string_template"),
3299
3301
  upstreamCreatedAt: integer("upstream_created_at"),
3300
3302
  upstreamUpdatedAt: integer("upstream_updated_at"),
3301
3303
  syncRunId: text("sync_run_id").references(() => runs.id, { onDelete: "set null" }),
@@ -3313,6 +3315,7 @@ var adsAdGroups = sqliteTable("ads_ad_groups", {
3313
3315
  billingEventType: text("billing_event_type"),
3314
3316
  maxBidMicros: integer("max_bid_micros"),
3315
3317
  contextHints: text("context_hints", { mode: "json" }).$type().notNull().default([]),
3318
+ landingPageQueryStringTemplate: text("landing_page_query_string_template"),
3316
3319
  upstreamCreatedAt: integer("upstream_created_at"),
3317
3320
  upstreamUpdatedAt: integer("upstream_updated_at"),
3318
3321
  syncRunId: text("sync_run_id").references(() => runs.id, { onDelete: "set null" }),
@@ -3329,6 +3332,7 @@ var adsAds = sqliteTable("ads_ads", {
3329
3332
  status: text("status").notNull(),
3330
3333
  creative: text("creative", { mode: "json" }).$type(),
3331
3334
  reviewStatus: text("review_status"),
3335
+ landingPageQueryStringTemplate: text("landing_page_query_string_template"),
3332
3336
  upstreamCreatedAt: integer("upstream_created_at"),
3333
3337
  upstreamUpdatedAt: integer("upstream_updated_at"),
3334
3338
  syncRunId: text("sync_run_id").references(() => runs.id, { onDelete: "set null" }),
@@ -7515,6 +7519,19 @@ var MIGRATION_VERSIONS = [
7515
7519
  `CREATE INDEX IF NOT EXISTS idx_run_fills_run ON run_fills(run_id, created_at)`,
7516
7520
  `CREATE INDEX IF NOT EXISTS idx_run_fills_project_status ON run_fills(project_id, status)`
7517
7521
  ]
7522
+ },
7523
+ {
7524
+ // Ad URL tracking parameters (`landing_page_configuration.
7525
+ // query_string_template` upstream): the provider appends them to every
7526
+ // click URL under the entity. Stored per level because campaign, ad group,
7527
+ // and ad each carry their own, and upstream combines them.
7528
+ version: 161,
7529
+ name: "ads-landing-page-tracking-template",
7530
+ statements: [
7531
+ `ALTER TABLE ads_campaigns ADD COLUMN landing_page_query_string_template TEXT`,
7532
+ `ALTER TABLE ads_ad_groups ADD COLUMN landing_page_query_string_template TEXT`,
7533
+ `ALTER TABLE ads_ads ADD COLUMN landing_page_query_string_template TEXT`
7534
+ ]
7518
7535
  }
7519
7536
  ];
7520
7537
  function addRunsMeasurementPlanVersionForeignKey(tx) {
@@ -19691,12 +19708,12 @@ function upsertCompetitor(authoring, body) {
19691
19708
  };
19692
19709
  }
19693
19710
  function removeCompetitor(authoring, body) {
19694
- const { groupKey, competitorKey } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
19711
+ const { groupKey, competitorKey: competitorKey2 } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
19695
19712
  requireGroup(authoring, groupKey);
19696
19713
  return {
19697
19714
  authoring: {
19698
19715
  ...authoring,
19699
- groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !== competitorKey) } : group)
19716
+ groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !== competitorKey2) } : group)
19700
19717
  },
19701
19718
  warnings: []
19702
19719
  };
@@ -40583,7 +40600,8 @@ var routeCatalog = [
40583
40600
  uniqueItems: true,
40584
40601
  items: stringSchema,
40585
40602
  description: "Optional conversion events to optimize delivery toward. Independent of biddingType: a clicks campaign may omit these."
40586
- }
40603
+ },
40604
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, description: "Tracking parameters appended to click URLs under this entity, as a bare query string (utm_source=chatgpt&utm_medium=cpc). Supports the {campaign_id}, {ad_group_id}, {ad_id}, {ad_account_id} and {oppref} macros. Levels combine; on a duplicate key the destination URL wins, then ad, ad group, campaign." }
40587
40605
  }
40588
40606
  } } }
40589
40607
  },
@@ -40615,7 +40633,8 @@ var routeCatalog = [
40615
40633
  description: stringSchema,
40616
40634
  contextHints: { type: "array", minItems: 1, maxItems: 100, items: stringSchema },
40617
40635
  maxBidMicros: { type: "integer", minimum: 1, maximum: 1e8 },
40618
- billingEventType: { type: "string", enum: Object.values(AdsAdGroupBillingEventTypes) }
40636
+ billingEventType: { type: "string", enum: Object.values(AdsAdGroupBillingEventTypes) },
40637
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, description: "Tracking parameters appended to click URLs under this entity, as a bare query string (utm_source=chatgpt&utm_medium=cpc). Supports the {campaign_id}, {ad_group_id}, {ad_id}, {ad_account_id} and {oppref} macros. Levels combine; on a duplicate key the destination URL wins, then ad, ad group, campaign." }
40619
40638
  }
40620
40639
  } } }
40621
40640
  },
@@ -40644,7 +40663,8 @@ var routeCatalog = [
40644
40663
  operationKey: adsOperationKeySchema,
40645
40664
  adGroupId: stringSchema,
40646
40665
  name: { type: "string", minLength: 3, maxLength: 1e3 },
40647
- creative: adsCreativeRequestSchema
40666
+ creative: adsCreativeRequestSchema,
40667
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, description: "Tracking parameters appended to click URLs under this entity, as a bare query string (utm_source=chatgpt&utm_medium=cpc). Supports the {campaign_id}, {ad_group_id}, {ad_id}, {ad_account_id} and {oppref} macros. Levels combine; on a duplicate key the destination URL wins, then ad, ad group, campaign." }
40648
40668
  }
40649
40669
  } } }
40650
40670
  },
@@ -40677,7 +40697,8 @@ var routeCatalog = [
40677
40697
  startTime: { type: "integer", nullable: true },
40678
40698
  endTime: { type: "integer", nullable: true },
40679
40699
  lifetimeSpendLimitMicros: { type: "integer", minimum: 1e6 },
40680
- locationIds: { type: "array", minItems: 1, maxItems: 100, items: stringSchema }
40700
+ locationIds: { type: "array", minItems: 1, maxItems: 100, items: stringSchema },
40701
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, nullable: true, description: "Tracking parameters appended to click URLs under this entity, as a bare query string. Null clears them." }
40681
40702
  }
40682
40703
  } } }
40683
40704
  },
@@ -40708,7 +40729,8 @@ var routeCatalog = [
40708
40729
  name: { type: "string", minLength: 3, maxLength: 1e3 },
40709
40730
  description: { type: "string", nullable: true },
40710
40731
  contextHints: { type: "array", minItems: 1, maxItems: 100, items: stringSchema },
40711
- maxBidMicros: { type: "integer", minimum: 1, maximum: 1e8 }
40732
+ maxBidMicros: { type: "integer", minimum: 1, maximum: 1e8 },
40733
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, nullable: true, description: "Tracking parameters appended to click URLs under this entity, as a bare query string. Null clears them." }
40712
40734
  }
40713
40735
  } } }
40714
40736
  },
@@ -40737,7 +40759,8 @@ var routeCatalog = [
40737
40759
  operationKey: adsOperationKeySchema,
40738
40760
  expectedUpdatedAt: integerSchema,
40739
40761
  name: { type: "string", minLength: 3, maxLength: 1e3 },
40740
- creative: adsCreativeRequestSchema
40762
+ creative: adsCreativeRequestSchema,
40763
+ landingPageQueryStringTemplate: { type: "string", minLength: 1, maxLength: 1e3, nullable: true, description: "Tracking parameters appended to click URLs under this entity, as a bare query string. Null clears them." }
40741
40764
  }
40742
40765
  } } }
40743
40766
  },
@@ -52444,7 +52467,8 @@ function campaignCreateReconcileFields(input) {
52444
52467
  lifetimeSpendLimitMicros: input.lifetimeSpendLimitMicros,
52445
52468
  locationIds: normalizeStringSet(input.locationIds),
52446
52469
  biddingType: input.biddingType,
52447
- conversionEventSettingIds: normalizeStringSet(input.conversionEventSettingIds ?? [])
52470
+ conversionEventSettingIds: normalizeStringSet(input.conversionEventSettingIds ?? []),
52471
+ ...input.landingPageQueryStringTemplate === void 0 ? {} : { landingPageQueryStringTemplate: input.landingPageQueryStringTemplate }
52448
52472
  };
52449
52473
  }
52450
52474
  function adGroupCreateReconcileFields(input) {
@@ -52455,7 +52479,8 @@ function adGroupCreateReconcileFields(input) {
52455
52479
  status: AdsEntityStatuses.paused,
52456
52480
  contextHints: normalizeStringSet(input.contextHints),
52457
52481
  maxBidMicros: input.maxBidMicros,
52458
- billingEventType: input.billingEventType
52482
+ billingEventType: input.billingEventType,
52483
+ ...input.landingPageQueryStringTemplate === void 0 ? {} : { landingPageQueryStringTemplate: input.landingPageQueryStringTemplate }
52459
52484
  };
52460
52485
  }
52461
52486
  function adCreateReconcileFields(input) {
@@ -52463,7 +52488,8 @@ function adCreateReconcileFields(input) {
52463
52488
  adGroupId: input.adGroupId,
52464
52489
  name: normalizeString(input.name),
52465
52490
  status: AdsEntityStatuses.paused,
52466
- creativeFingerprint: creativeFingerprint(input.creative)
52491
+ creativeFingerprint: creativeFingerprint(input.creative),
52492
+ ...input.landingPageQueryStringTemplate === void 0 ? {} : { landingPageQueryStringTemplate: input.landingPageQueryStringTemplate }
52467
52493
  };
52468
52494
  }
52469
52495
  function updateReconcileFields(entityType, update) {
@@ -52471,6 +52497,10 @@ function updateReconcileFields(entityType, update) {
52471
52497
  if (typeof update.name === "string") fields.name = normalizeString(update.name);
52472
52498
  if (update.description === null) fields.description = null;
52473
52499
  else if (typeof update.description === "string") fields.description = normalizeString(update.description);
52500
+ if (update.landingPageQueryStringTemplate === null) fields.landingPageQueryStringTemplate = null;
52501
+ else if (typeof update.landingPageQueryStringTemplate === "string") {
52502
+ fields.landingPageQueryStringTemplate = update.landingPageQueryStringTemplate;
52503
+ }
52474
52504
  if (entityType === AdsEntityTypes.campaign) {
52475
52505
  if (update.startTime === null || typeof update.startTime === "number") fields.startTime = update.startTime;
52476
52506
  if (update.endTime === null || typeof update.endTime === "number") fields.endTime = update.endTime;
@@ -52512,6 +52542,10 @@ function entityReconcileFields(entity) {
52512
52542
  } else if (Array.isArray(entity.conversionEventSettingIds)) {
52513
52543
  fields.conversionEventSettingIds = normalizeStringSet(entity.conversionEventSettingIds);
52514
52544
  }
52545
+ if (entity.landingPageQueryStringTemplate === null) fields.landingPageQueryStringTemplate = null;
52546
+ else if (typeof entity.landingPageQueryStringTemplate === "string") {
52547
+ fields.landingPageQueryStringTemplate = entity.landingPageQueryStringTemplate;
52548
+ }
52515
52549
  if (typeof entity.campaignId === "string") fields.campaignId = entity.campaignId;
52516
52550
  if (Array.isArray(entity.contextHints)) fields.contextHints = normalizeStringSet(entity.contextHints);
52517
52551
  if (typeof entity.maxBidMicros === "number") fields.maxBidMicros = entity.maxBidMicros;
@@ -54055,6 +54089,7 @@ async function adsRoutes(app, opts) {
54055
54089
  status: ad.status,
54056
54090
  reviewStatus: ad.reviewStatus,
54057
54091
  creative: creativeDto(ad.creative),
54092
+ landingPageQueryStringTemplate: ad.landingPageQueryStringTemplate,
54058
54093
  upstreamUpdatedAt: ad.upstreamUpdatedAt,
54059
54094
  syncedAt: ad.syncedAt
54060
54095
  };
@@ -54074,6 +54109,7 @@ async function adsRoutes(app, opts) {
54074
54109
  maxBidMicros: group.maxBidMicros,
54075
54110
  contextHints: group.contextHints,
54076
54111
  ads: adsByGroup.get(group.id) ?? [],
54112
+ landingPageQueryStringTemplate: group.landingPageQueryStringTemplate,
54077
54113
  upstreamUpdatedAt: group.upstreamUpdatedAt,
54078
54114
  syncedAt: group.syncedAt
54079
54115
  };
@@ -54094,6 +54130,7 @@ async function adsRoutes(app, opts) {
54094
54130
  lifetimeSpendLimitMicros: campaign.lifetimeSpendLimitMicros,
54095
54131
  locationIds: locationIdsDto(campaign.targeting),
54096
54132
  adGroups: groupsByCampaign.get(campaign.id) ?? [],
54133
+ landingPageQueryStringTemplate: campaign.landingPageQueryStringTemplate,
54097
54134
  upstreamUpdatedAt: campaign.upstreamUpdatedAt,
54098
54135
  syncedAt: campaign.syncedAt
54099
54136
  }));
@@ -85596,9 +85633,88 @@ function utcDayBounds(now) {
85596
85633
  return { start, end, date };
85597
85634
  }
85598
85635
 
85636
+ // ../api-routes/src/plan-competitors.ts
85637
+ import { eq as eq69 } from "drizzle-orm";
85638
+ function competitorKey(value) {
85639
+ const host = (hostOf(value) ?? value).trim().toLowerCase().replace(/\.$/, "");
85640
+ return host.startsWith("www.") ? host.slice(4) : host;
85641
+ }
85642
+ function merge(into, domain, names) {
85643
+ const key = competitorKey(domain);
85644
+ if (!key) return;
85645
+ const set = into.get(key) ?? /* @__PURE__ */ new Set();
85646
+ for (const name of names) if (name.trim()) set.add(name.trim());
85647
+ into.set(key, set);
85648
+ }
85649
+ function toList(merged) {
85650
+ return [...merged].sort(([left], [right]) => left.localeCompare(right)).map(([domain, names]) => ({ domain, aliases: [...names] }));
85651
+ }
85652
+ function readScope(db, versionId) {
85653
+ const row = db.select({ canonicalJson: measurementPlanVersions.canonicalJson }).from(measurementPlanVersions).where(eq69(measurementPlanVersions.id, versionId)).get();
85654
+ if (!row) return null;
85655
+ let groups;
85656
+ let edges;
85657
+ try {
85658
+ const plan = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
85659
+ if (plan.schemaVersion === MEASUREMENT_PLAN_V2_SCHEMA_VERSION) {
85660
+ groups = plan.groups.map((group) => ({
85661
+ targetKeys: group.targetKeys,
85662
+ competitors: group.competitors.map((competitor) => ({ domain: competitor.domain, names: [competitor.label, ...competitor.aliases] }))
85663
+ }));
85664
+ edges = plan.usageEdges;
85665
+ } else {
85666
+ groups = plan.groups.map((group) => ({
85667
+ targetKeys: group.targetKeys,
85668
+ competitors: (group.competitors ?? []).map((domain) => ({ domain, names: [] }))
85669
+ }));
85670
+ edges = plan.usageEdges.flatMap((edge) => edge.kind === "target" ? [edge] : []);
85671
+ }
85672
+ } catch {
85673
+ return null;
85674
+ }
85675
+ const all = /* @__PURE__ */ new Map();
85676
+ const groupsByTarget = /* @__PURE__ */ new Map();
85677
+ groups.forEach((group, index2) => {
85678
+ for (const competitor of group.competitors) merge(all, competitor.domain, competitor.names);
85679
+ for (const target of group.targetKeys) groupsByTarget.set(target, [...groupsByTarget.get(target) ?? [], index2]);
85680
+ });
85681
+ const nodeGroups = /* @__PURE__ */ new Map();
85682
+ for (const edge of edges) {
85683
+ const set = nodeGroups.get(edge.executionNodeKey) ?? /* @__PURE__ */ new Set();
85684
+ for (const index2 of groupsByTarget.get(edge.targetKey) ?? []) set.add(index2);
85685
+ nodeGroups.set(edge.executionNodeKey, set);
85686
+ }
85687
+ const byNode = /* @__PURE__ */ new Map();
85688
+ for (const [node, indexes] of nodeGroups) {
85689
+ const merged = /* @__PURE__ */ new Map();
85690
+ for (const index2 of indexes) for (const competitor of groups[index2].competitors) merge(merged, competitor.domain, competitor.names);
85691
+ byNode.set(node, toList(merged));
85692
+ }
85693
+ return { all: toList(all), byNode };
85694
+ }
85695
+ function createRunCompetitorResolver(db, projectCompetitorDomains) {
85696
+ const scopes = /* @__PURE__ */ new Map();
85697
+ const listOnly = () => ({ domains: [...new Set(projectCompetitorDomains)], aliases: /* @__PURE__ */ new Map() });
85698
+ return (versionId, executionId) => {
85699
+ if (!versionId || !executionId) return listOnly();
85700
+ if (!scopes.has(versionId)) scopes.set(versionId, readScope(db, versionId));
85701
+ const pinned = scopes.get(versionId)?.byNode.get(executionId) ?? [];
85702
+ if (pinned.length === 0) return listOnly();
85703
+ const byKey = /* @__PURE__ */ new Map();
85704
+ for (const domain of projectCompetitorDomains) if (!byKey.has(competitorKey(domain))) byKey.set(competitorKey(domain), domain);
85705
+ const aliases = /* @__PURE__ */ new Map();
85706
+ for (const competitor of pinned) {
85707
+ const domain = byKey.get(competitor.domain) ?? competitor.domain;
85708
+ byKey.set(competitor.domain, domain);
85709
+ if (competitor.aliases.length) aliases.set(domain, competitor.aliases);
85710
+ }
85711
+ return { domains: [.../* @__PURE__ */ new Set([...projectCompetitorDomains, ...byKey.values()])], aliases };
85712
+ };
85713
+ }
85714
+
85599
85715
  // ../api-routes/src/simple-measurement-definitions.ts
85600
85716
  import crypto51 from "crypto";
85601
- import { and as and59, eq as eq69 } from "drizzle-orm";
85717
+ import { and as and59, eq as eq70 } from "drizzle-orm";
85602
85718
  function captureSimpleMeasurementDefinition(db, input) {
85603
85719
  return db.transaction((tx) => {
85604
85720
  const run = tx.select({
@@ -85606,7 +85722,7 @@ function captureSimpleMeasurementDefinition(db, input) {
85606
85722
  trigger: runs.trigger,
85607
85723
  status: runs.status,
85608
85724
  measurementPlanVersionId: runs.measurementPlanVersionId
85609
- }).from(runs).where(and59(eq69(runs.projectId, input.projectId), eq69(runs.id, input.runId))).get();
85725
+ }).from(runs).where(and59(eq70(runs.projectId, input.projectId), eq70(runs.id, input.runId))).get();
85610
85726
  if (!run) throw notFound("Run", input.runId);
85611
85727
  if (run.kind !== RunKinds["answer-visibility"] || run.trigger === RunTriggers.probe || run.measurementPlanVersionId !== null) {
85612
85728
  return null;
@@ -85616,7 +85732,7 @@ function captureSimpleMeasurementDefinition(db, input) {
85616
85732
  if (definition.queries.some((query) => query.queryClass !== (classifier?.classify(query.queryText) ?? null))) {
85617
85733
  throw validationError("Query classes must match the captured identity and text.");
85618
85734
  }
85619
- const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(eq69(simpleMeasurementDefinitions.projectId, input.projectId), eq69(simpleMeasurementDefinitions.runId, input.runId))).get();
85735
+ const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(eq70(simpleMeasurementDefinitions.projectId, input.projectId), eq70(simpleMeasurementDefinitions.runId, input.runId))).get();
85620
85736
  if (existing) {
85621
85737
  const frozen = simpleMeasurementDefinitionSchema.parse(existing.definition);
85622
85738
  const replayDefinition = {
@@ -85637,15 +85753,15 @@ function captureSimpleMeasurementDefinition(db, input) {
85637
85753
  if (run.status !== RunStatuses.running) {
85638
85754
  throw validationError("Only a running run can capture a new measurement definition.");
85639
85755
  }
85640
- if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq69(querySnapshots.runId, input.runId)).limit(1).get()) {
85756
+ if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq70(querySnapshots.runId, input.runId)).limit(1).get()) {
85641
85757
  throw validationError("This run already has stored answers. Its measurement definition cannot be inferred afterward.");
85642
85758
  }
85643
- const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq69(queries.projectId, input.projectId)).all().map((query) => query.id));
85759
+ const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq70(queries.projectId, input.projectId)).all().map((query) => query.id));
85644
85760
  if (definition.queries.some((query) => !projectQueryIds.has(query.queryId))) {
85645
85761
  throw validationError("Every captured query must belong to the run project.");
85646
85762
  }
85647
85763
  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));
85764
+ const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(eq70(competitors.projectId, input.projectId)).all().map((competitor) => competitor.domain));
85649
85765
  const capturedDomains = new Set(definition.competitors.map((competitor) => competitor.domain));
85650
85766
  if (liveCompetitorDomains.size !== capturedDomains.size || [...liveCompetitorDomains].some((domain) => !capturedDomains.has(domain))) {
85651
85767
  throw validationError("Captured competitors must exactly match the project competitors dispatched for this run.");
@@ -86462,7 +86578,7 @@ function determineCitationState(normalized, domains) {
86462
86578
  }
86463
86579
  return "not-cited";
86464
86580
  }
86465
- function computeCompetitorOverlap(normalized, competitorDomains) {
86581
+ function computeCompetitorOverlap(normalized, competitorDomains, competitorAliases = /* @__PURE__ */ new Map()) {
86466
86582
  const overlapSet = /* @__PURE__ */ new Set();
86467
86583
  for (const d of normalized.citedDomains) {
86468
86584
  for (const cd of competitorDomains) {
@@ -86487,6 +86603,10 @@ function computeCompetitorOverlap(normalized, competitorDomains) {
86487
86603
  if (brandKeyFromText(brand).length >= 4 && textContainsBrandAlias(normalized.answerText, brand)) {
86488
86604
  overlapSet.add(cd);
86489
86605
  }
86606
+ const named = competitorAliases.get(cd);
86607
+ if (named?.length && textContainsAnyBrandAlias(normalized.answerText, named)) {
86608
+ overlapSet.add(cd);
86609
+ }
86490
86610
  }
86491
86611
  }
86492
86612
  return [...overlapSet];
@@ -86500,7 +86620,7 @@ function computeCitedCompetitorDomains(citedDomains, competitorDomains) {
86500
86620
  }
86501
86621
  return [...citedCompetitors];
86502
86622
  }
86503
- function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = []) {
86623
+ function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = [], competitorAliases = /* @__PURE__ */ new Map()) {
86504
86624
  if (!answerText || answerText.length < 20) return [];
86505
86625
  const ownBrandAliases = new Set(
86506
86626
  ownDomains.flatMap((domain) => collectBrandAliasesFromDomain(domain))
@@ -86510,7 +86630,7 @@ function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, com
86510
86630
  }
86511
86631
  const ownKeys = new Set([...ownBrandAliases].map(brandKeyFromText));
86512
86632
  const knownCompetitorAliases = new Set(
86513
- [...citedDomains, ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
86633
+ [...citedDomains.filter((domain) => !isListingMarketplace(domain)), ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).concat([...competitorAliases.values()].flat()).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
86514
86634
  );
86515
86635
  if (knownCompetitorAliases.size === 0) return [];
86516
86636
  const candidatePatterns = [
@@ -86592,10 +86712,10 @@ var log = createLogger("IntelligenceService");
86592
86712
  var runChronologyKey = sql28`coalesce(${runs.finishedAt}, ${runs.createdAt})`;
86593
86713
  function analyzableRunPredicates(projectId) {
86594
86714
  return [
86595
- eq70(runs.projectId, projectId),
86715
+ eq71(runs.projectId, projectId),
86596
86716
  // 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)),
86717
+ eq71(runs.kind, RunKinds["answer-visibility"]),
86718
+ or18(eq71(runs.status, RunStatuses.completed), eq71(runs.status, RunStatuses.partial)),
86599
86719
  // Defensive: RunCoordinator already skips probes before analyzeAndPersist
86600
86720
  // is called, but a future call site invoking it directly for a probe must
86601
86721
  // still not pollute the intelligence window.
@@ -86640,7 +86760,7 @@ var IntelligenceService = class {
86640
86760
  * Returns the analysis result for the coordinator to inspect (e.g. for webhook dispatch).
86641
86761
  */
86642
86762
  analyzeAndPersist(runId, projectId) {
86643
- const currentRunRecord = this.db.select().from(runs).where(and60(eq70(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
86763
+ const currentRunRecord = this.db.select().from(runs).where(and60(eq71(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
86644
86764
  if (!currentRunRecord) {
86645
86765
  log.info("intelligence.skip", { runId, reason: "run not eligible for analysis" });
86646
86766
  return null;
@@ -86649,7 +86769,7 @@ var IntelligenceService = class {
86649
86769
  const recentRuns = this.db.select().from(runs).where(
86650
86770
  and60(
86651
86771
  ...analyzableRunPredicates(projectId),
86652
- currentLocation === null ? isNull13(runs.location) : eq70(runs.location, currentLocation),
86772
+ currentLocation === null ? isNull13(runs.location) : eq71(runs.location, currentLocation),
86653
86773
  // Never look forward. The window is this run's own past, so
86654
86774
  // re-analyzing a historical run compares it against its true
86655
86775
  // predecessor rather than against sweeps that came after it.
@@ -86657,7 +86777,7 @@ var IntelligenceService = class {
86657
86777
  // MEASUREMENT: only runs that actually wrote snapshots — see above.
86658
86778
  // Index seek on idx_snapshots_run, short-circuited on the first row.
86659
86779
  exists(
86660
- this.db.select({ one: sql28`1` }).from(querySnapshots).where(eq70(querySnapshots.runId, runs.id))
86780
+ this.db.select({ one: sql28`1` }).from(querySnapshots).where(eq71(querySnapshots.runId, runs.id))
86661
86781
  )
86662
86782
  )
86663
86783
  ).orderBy(desc32(runs.finishedAt), desc32(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
@@ -86732,7 +86852,7 @@ var IntelligenceService = class {
86732
86852
  * Returns the persisted insights so the coordinator can count critical/high.
86733
86853
  */
86734
86854
  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();
86855
+ const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq71(runs.id, runId)).get();
86736
86856
  if (!runRow) {
86737
86857
  log.info("gbp-intelligence.skip", { runId, reason: "run not found" });
86738
86858
  this.persistGbpInsights(runId, projectId, [], []);
@@ -86741,8 +86861,8 @@ var IntelligenceService = class {
86741
86861
  const windowStart = runRow.startedAt ?? runRow.createdAt;
86742
86862
  const windowEnd = runRow.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString();
86743
86863
  const selected = this.db.select().from(gbpLocations).where(and60(
86744
- eq70(gbpLocations.projectId, projectId),
86745
- eq70(gbpLocations.selected, true),
86864
+ eq71(gbpLocations.projectId, projectId),
86865
+ eq71(gbpLocations.selected, true),
86746
86866
  gte18(gbpLocations.syncedAt, windowStart),
86747
86867
  lte15(gbpLocations.syncedAt, windowEnd)
86748
86868
  )).all();
@@ -86777,12 +86897,12 @@ var IntelligenceService = class {
86777
86897
  }
86778
86898
  /** Build the per-location signal bundle the GBP analyzer consumes. */
86779
86899
  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();
86900
+ 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();
86901
+ const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and60(eq71(gbpPlaceActions.projectId, projectId), eq71(gbpPlaceActions.locationName, locationName))).all();
86902
+ 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();
86903
+ const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and60(eq71(gbpLocations.projectId, projectId), eq71(gbpLocations.locationName, locationName))).get();
86784
86904
  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();
86905
+ 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
86906
  const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
86787
86907
  const summary3 = buildGbpSummary({
86788
86908
  locationName,
@@ -86818,7 +86938,7 @@ var IntelligenceService = class {
86818
86938
  /** Build the month-over-month keyword series for a location from the
86819
86939
  * accumulating gbp_keyword_monthly table (latest complete month vs prior). */
86820
86940
  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();
86941
+ 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
86942
  if (rows.length === 0) return { recentMonth: null, priorMonth: null, points: [] };
86823
86943
  const months = [...new Set(rows.map((r) => r.month))].sort().reverse();
86824
86944
  const recentMonth = months[0] ?? null;
@@ -86849,7 +86969,7 @@ var IntelligenceService = class {
86849
86969
  */
86850
86970
  persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
86851
86971
  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();
86972
+ 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
86973
  const staleIds = [];
86854
86974
  const dismissedSlots = /* @__PURE__ */ new Set();
86855
86975
  for (const row of existing) {
@@ -86860,7 +86980,7 @@ var IntelligenceService = class {
86860
86980
  }
86861
86981
  this.db.transaction((tx) => {
86862
86982
  for (const id of staleIds) {
86863
- tx.delete(insights).where(eq70(insights.id, id)).run();
86983
+ tx.delete(insights).where(eq71(insights.id, id)).run();
86864
86984
  }
86865
86985
  for (const insight of gbpInsights) {
86866
86986
  const parsed = parseGbpInsightId(insight.id);
@@ -86946,7 +87066,7 @@ var IntelligenceService = class {
86946
87066
  * create per run + aggregate). DB is left untouched.
86947
87067
  */
86948
87068
  backfill(projectName, opts, onProgress) {
86949
- const project = this.db.select().from(projects).where(eq70(projects.name, projectName)).get();
87069
+ const project = this.db.select().from(projects).where(eq71(projects.name, projectName)).get();
86950
87070
  if (!project) {
86951
87071
  throw new Error(`Project "${projectName}" not found`);
86952
87072
  }
@@ -87035,7 +87155,7 @@ var IntelligenceService = class {
87035
87155
  return { processed, skipped: skipped3, totalInsights };
87036
87156
  }
87037
87157
  loadTrackedCompetitors(projectId) {
87038
- return this.db.select({ domain: competitors.domain }).from(competitors).where(eq70(competitors.projectId, projectId)).all().map((r) => r.domain);
87158
+ return this.db.select({ domain: competitors.domain }).from(competitors).where(eq71(competitors.projectId, projectId)).all().map((r) => r.domain);
87039
87159
  }
87040
87160
  /**
87041
87161
  * Which of `runIds` actually wrote query snapshots. One grouped read, so
@@ -87066,15 +87186,15 @@ var IntelligenceService = class {
87066
87186
  }
87067
87187
  persistResult(result, runId, projectId) {
87068
87188
  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();
87189
+ 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
87190
  for (const row of existingInsights) {
87071
87191
  if (row.dismissed) {
87072
87192
  previouslyDismissed.add(`${row.query}:${row.provider}:${row.type}`);
87073
87193
  }
87074
87194
  }
87075
87195
  this.db.transaction((tx) => {
87076
- tx.delete(insights).where(eq70(insights.runId, runId)).run();
87077
- tx.delete(healthSnapshots).where(eq70(healthSnapshots.runId, runId)).run();
87196
+ tx.delete(insights).where(eq71(insights.runId, runId)).run();
87197
+ tx.delete(healthSnapshots).where(eq71(healthSnapshots.runId, runId)).run();
87078
87198
  const now = (/* @__PURE__ */ new Date()).toISOString();
87079
87199
  for (const insight of result.insights) {
87080
87200
  const wasDismissed = previouslyDismissed.has(`${insight.query}:${insight.provider}:${insight.type}`);
@@ -87122,7 +87242,7 @@ var IntelligenceService = class {
87122
87242
  impressions: gscSearchData.impressions,
87123
87243
  position: gscSearchData.position
87124
87244
  }).from(gscSearchData).where(and60(
87125
- eq70(gscSearchData.projectId, projectId),
87245
+ eq71(gscSearchData.projectId, projectId),
87126
87246
  gte18(gscSearchData.date, window.startDate),
87127
87247
  lte15(gscSearchData.date, window.endDate)
87128
87248
  )).all();
@@ -87175,7 +87295,7 @@ var IntelligenceService = class {
87175
87295
  const key = row.query.toLowerCase();
87176
87296
  gscImpressionsByQuery.set(key, (gscImpressionsByQuery.get(key) ?? 0) + row.impressions);
87177
87297
  }
87178
- const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq70(projects.id, projectId)).get();
87298
+ const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq71(projects.id, projectId)).get();
87179
87299
  const locationCount = Math.max(
87180
87300
  1,
87181
87301
  (projectRow?.locations ?? []).length
@@ -87183,9 +87303,9 @@ var IntelligenceService = class {
87183
87303
  const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
87184
87304
  const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
87185
87305
  and60(
87186
- eq70(runs.projectId, projectId),
87187
- eq70(runs.kind, RunKinds["answer-visibility"]),
87188
- or18(eq70(runs.status, "completed"), eq70(runs.status, "partial")),
87306
+ eq71(runs.projectId, projectId),
87307
+ eq71(runs.kind, RunKinds["answer-visibility"]),
87308
+ or18(eq71(runs.status, "completed"), eq71(runs.status, "partial")),
87189
87309
  // Defensive — see top of file.
87190
87310
  ne11(runs.trigger, RunTriggers.probe)
87191
87311
  )
@@ -87205,7 +87325,7 @@ var IntelligenceService = class {
87205
87325
  const haveHistory = recentRunIds.length > 0;
87206
87326
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
87207
87327
  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();
87328
+ 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
87329
  const regressionGroups = /* @__PURE__ */ new Map();
87210
87330
  for (const row of priorRows) {
87211
87331
  if (!row.runId) continue;
@@ -87234,7 +87354,7 @@ var IntelligenceService = class {
87234
87354
  });
87235
87355
  }
87236
87356
  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();
87357
+ const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(eq71(projects.id, projectId)).get();
87238
87358
  const projectDomains = projectDomainRow ? effectiveDomains({
87239
87359
  canonicalDomain: projectDomainRow.canonicalDomain,
87240
87360
  ownedDomains: projectDomainRow.ownedDomains
@@ -87252,7 +87372,7 @@ var IntelligenceService = class {
87252
87372
  citedDomains: querySnapshots.citedDomains,
87253
87373
  rawResponse: querySnapshots.rawResponse,
87254
87374
  snapshotLocation: querySnapshots.location
87255
- }).from(querySnapshots).leftJoin(queries, eq70(querySnapshots.queryId, queries.id)).where(eq70(querySnapshots.runId, runId)).all();
87375
+ }).from(querySnapshots).leftJoin(queries, eq71(querySnapshots.queryId, queries.id)).where(eq71(querySnapshots.runId, runId)).all();
87256
87376
  const snapshots = [];
87257
87377
  let orphanCount = 0;
87258
87378
  for (const r of rows) {
@@ -87473,6 +87593,7 @@ export {
87473
87593
  runChecks,
87474
87594
  executeDiscovery,
87475
87595
  markSessionFailed,
87596
+ createRunCompetitorResolver,
87476
87597
  captureSimpleMeasurementDefinition,
87477
87598
  apiRoutes,
87478
87599
  addLogListener,
@@ -5,12 +5,12 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-Q35D2R2P.js";
8
+ } from "./chunk-3YAPVVFN.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-L36TC6LB.js";
14
14
 
15
15
  // src/site-crawl-graph-layout.ts
16
16
  import crypto from "crypto";
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-IPGBK7XR.js";
7
+ } from "./chunk-ZGZSROSR.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-L36TC6LB.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";