@ainyc/canonry 5.3.0 → 5.3.1

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.
@@ -5,7 +5,7 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-QAGZWYPI.js";
8
+ } from "./chunk-IACO5R7A.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
@@ -1386,7 +1386,17 @@ var doctorHealthState = sqliteTable("doctor_health_state", {
1386
1386
  summary: text("summary").notNull(),
1387
1387
  checkedAt: text("checked_at").notNull(),
1388
1388
  /** When we last emitted for this (status, code). Null until first emit. */
1389
- notifiedAt: text("notified_at")
1389
+ notifiedAt: text("notified_at"),
1390
+ /**
1391
+ * Every failing check from the last pass as sorted `status:code` pairs. The
1392
+ * headline code alone cannot see a second breach arriving UNDER an existing
1393
+ * one: a GBP outage opening beneath a standing GA warning left the worst code
1394
+ * unchanged, so it was graded, listed in the payload, and then never sent.
1395
+ * NULL on rows written before this column existed — unknown is not the same
1396
+ * as changed, so the trigger falls back to the code rule for one pass rather
1397
+ * than paging every already-degraded project the moment this ships.
1398
+ */
1399
+ failingSignature: text("failing_signature")
1390
1400
  });
1391
1401
  var siteLivenessState = sqliteTable("site_liveness_state", {
1392
1402
  projectId: text("project_id").primaryKey(),
@@ -7322,6 +7332,17 @@ var MIGRATION_VERSIONS = [
7322
7332
  notified_at TEXT
7323
7333
  )`
7324
7334
  ]
7335
+ },
7336
+ {
7337
+ // A breach opening underneath an existing one never reached anyone: the
7338
+ // trigger keyed on the worst check's code, and a lower-ranked check going
7339
+ // bad does not change it. Existing rows get NULL, which the notifier reads
7340
+ // as "unknown" rather than "changed" so shipping this pages nobody.
7341
+ version: 157,
7342
+ name: "doctor-health-failing-signature",
7343
+ statements: [
7344
+ `ALTER TABLE doctor_health_state ADD COLUMN failing_signature TEXT`
7345
+ ]
7325
7346
  }
7326
7347
  ];
7327
7348
  function addRunsMeasurementPlanVersionForeignKey(tx) {
@@ -79915,7 +79936,7 @@ var SITE_REACHABILITY_CHECKS = [siteReachabilityCheck];
79915
79936
 
79916
79937
  // ../api-routes/src/doctor/checks/gbp-auth.ts
79917
79938
  import { and as and52, eq as eq60 } from "drizzle-orm";
79918
- var RECENT_SYNC_WARN_DAYS2 = 7;
79939
+ var RECENT_SYNC_WARN_DAYS2 = 4;
79919
79940
  var RECENT_SYNC_FAIL_DAYS2 = 30;
79920
79941
  function skippedNoProject3() {
79921
79942
  return {
@@ -21,7 +21,7 @@ import {
21
21
  deleteSiteCrawlGraphLayout,
22
22
  persistSiteCrawlGraphLayout,
23
23
  prepareSiteCrawlGraphLayout
24
- } from "./chunk-MNUFMEAX.js";
24
+ } from "./chunk-3COTRCK3.js";
25
25
  import {
26
26
  PACKAGE_VERSION
27
27
  } from "./chunk-AOJU5LKX.js";
@@ -176,7 +176,7 @@ import {
176
176
  siteLivenessState,
177
177
  toAlertView,
178
178
  usageCounters
179
- } from "./chunk-QAGZWYPI.js";
179
+ } from "./chunk-IACO5R7A.js";
180
180
  import {
181
181
  AGENT_MEMORY_VALUE_MAX_BYTES,
182
182
  AGENT_NONE,
@@ -6461,7 +6461,7 @@ function nonBlank(value) {
6461
6461
  return trimmed ? trimmed : void 0;
6462
6462
  }
6463
6463
  function resolveBuildCommit(env = process.env) {
6464
- const embedded = true ? "caba5d386b2538f0fb2e4b23c1275a1c8c652fbd" : void 0;
6464
+ const embedded = true ? "faea7a16b83966f055c85e798a03c0a4108c1377" : void 0;
6465
6465
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
6466
6466
  }
6467
6467
  function resolveInstanceIdentity(env = process.env) {
@@ -11755,7 +11755,7 @@ function readStoredGroundingSources(rawResponse) {
11755
11755
  return result;
11756
11756
  }
11757
11757
  async function backfillInsightsCommand(project, opts) {
11758
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-PR6T6JKY.js");
11758
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-H34EOB6K.js");
11759
11759
  const config = loadConfig();
11760
11760
  const db = createClient(config.database);
11761
11761
  migrate(db);
@@ -13101,6 +13101,7 @@ var Notifier = class {
13101
13101
  const summary = noSignal ? `No health check produced a result (${report.checks.length} skipped) \u2014 health is unknown, not confirmed.` : worst?.summary ?? `All ${graded.length} health check(s) passing.`;
13102
13102
  const previous = this.db.select().from(doctorHealthState).where(eq17(doctorHealthState.projectId, projectId)).get();
13103
13103
  const previousStatus = previous?.status ?? null;
13104
+ const failingSignature = failing.map((c) => `${c.status}:${c.code}`).join(",");
13104
13105
  let event = null;
13105
13106
  if (previous === void 0) {
13106
13107
  if (status !== "ok") event = "health.degraded";
@@ -13108,9 +13109,11 @@ var Notifier = class {
13108
13109
  event = "health.recovered";
13109
13110
  } else if (status !== "ok" && (previousStatus === "ok" || previous.code !== code)) {
13110
13111
  event = "health.degraded";
13112
+ } else if (status !== "ok" && previous.failingSignature !== null && previous.failingSignature !== failingSignature) {
13113
+ event = "health.degraded";
13111
13114
  }
13112
13115
  const now = report.checkedAt;
13113
- const observation = { projectId, status, code, summary, checkedAt: now };
13116
+ const observation = { projectId, status, code, summary, checkedAt: now, failingSignature };
13114
13117
  if (previous === void 0) {
13115
13118
  this.db.insert(doctorHealthState).values({ ...observation, notifiedAt: null }).run();
13116
13119
  } else {
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  trackCliCommandFinished,
34
34
  trackEvent,
35
35
  waitForServerRuntimeStartup
36
- } from "./chunk-HOOU4NS2.js";
36
+ } from "./chunk-TF6HFT3Q.js";
37
37
  import {
38
38
  autoSyncSkills,
39
39
  formatAutoSyncNotice
@@ -69,7 +69,7 @@ import {
69
69
  trustedProxiesProblem,
70
70
  trustedProxyProblem
71
71
  } from "./chunk-RB2F4D3Z.js";
72
- import "./chunk-MNUFMEAX.js";
72
+ import "./chunk-3COTRCK3.js";
73
73
  import "./chunk-AOJU5LKX.js";
74
74
  import {
75
75
  CLOUDFLARE_WORKER_BINDINGS,
@@ -84,7 +84,7 @@ import {
84
84
  projects,
85
85
  queries,
86
86
  renderReportHtml
87
- } from "./chunk-QAGZWYPI.js";
87
+ } from "./chunk-IACO5R7A.js";
88
88
  import {
89
89
  AdsDeliverySnapshotStatuses,
90
90
  AdsHistoricalCampaignRollupStatuses,
@@ -428,7 +428,7 @@ function parseDemoTrustedProxies(values) {
428
428
  async function demoCommand(options) {
429
429
  const { host, port } = parseDemoListenOptions(options);
430
430
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
431
- const { createDemoServer } = await import("./demo-server-Y7YWLPU7.js");
431
+ const { createDemoServer } = await import("./demo-server-TXW3UX3P.js");
432
432
  const app = await createDemoServer({ trustProxy });
433
433
  let stopping = false;
434
434
  const stop = () => {
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  layoutSiteCrawlGraphInput,
6
6
  persistSiteCrawlGraphLayout
7
- } from "./chunk-MNUFMEAX.js";
7
+ } from "./chunk-3COTRCK3.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-QAGZWYPI.js";
86
+ } from "./chunk-IACO5R7A.js";
87
87
  import {
88
88
  RunKinds,
89
89
  SiteCrawlFetchStates,
package/dist/index.js CHANGED
@@ -3,13 +3,13 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-HOOU4NS2.js";
6
+ } from "./chunk-TF6HFT3Q.js";
7
7
  import {
8
8
  loadConfig
9
9
  } from "./chunk-IOP36L3C.js";
10
- import "./chunk-MNUFMEAX.js";
10
+ import "./chunk-3COTRCK3.js";
11
11
  import "./chunk-AOJU5LKX.js";
12
- import "./chunk-QAGZWYPI.js";
12
+ import "./chunk-IACO5R7A.js";
13
13
  import "./chunk-2U5IW3G5.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-QAGZWYPI.js";
4
+ } from "./chunk-IACO5R7A.js";
5
5
  import "./chunk-2U5IW3G5.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "5.3.0",
3
+ "version": "5.3.1",
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": [
@@ -87,31 +87,31 @@
87
87
  "tsup": "^8.5.1",
88
88
  "tsx": "^4.19.0",
89
89
  "@ainyc/canonry-web": "0.0.0",
90
- "@ainyc/canonry-api-routes": "0.0.0",
91
90
  "@ainyc/canonry-api-client": "0.0.0",
92
91
  "@ainyc/canonry-config": "0.0.0",
93
92
  "@ainyc/canonry-contracts": "0.0.0",
94
- "@ainyc/canonry-db": "0.0.0",
93
+ "@ainyc/canonry-api-routes": "0.0.0",
95
94
  "@ainyc/canonry-integration-bing": "0.0.0",
95
+ "@ainyc/canonry-db": "0.0.0",
96
96
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
97
- "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
98
- "@ainyc/canonry-integration-google": "0.0.0",
99
97
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
100
- "@ainyc/canonry-integration-google-ads": "0.0.0",
98
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
99
+ "@ainyc/canonry-integration-google": "0.0.0",
100
+ "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
101
101
  "@ainyc/canonry-integration-google-places": "0.0.0",
102
102
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
103
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
103
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
104
104
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
105
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
106
105
  "@ainyc/canonry-integration-traffic": "0.0.0",
106
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
107
107
  "@ainyc/canonry-integration-wordpress": "0.0.0",
108
- "@ainyc/canonry-intelligence": "0.0.0",
109
108
  "@ainyc/canonry-provider-cdp": "0.0.0",
110
109
  "@ainyc/canonry-provider-claude": "0.0.0",
110
+ "@ainyc/canonry-intelligence": "0.0.0",
111
111
  "@ainyc/canonry-provider-gemini": "0.0.0",
112
+ "@ainyc/canonry-provider-openai": "0.0.0",
112
113
  "@ainyc/canonry-provider-local": "0.0.0",
113
- "@ainyc/canonry-provider-perplexity": "0.0.0",
114
- "@ainyc/canonry-provider-openai": "0.0.0"
114
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
115
115
  },
116
116
  "scripts": {
117
117
  "build": "pnpm run build:cli && pnpm run build:web",