@canonry/canonry 4.178.2 → 4.178.4
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.
- package/dist/{chunk-EAUE2RRY.js → chunk-EBRGLDTB.js} +2 -2
- package/dist/{chunk-P6JVZJO5.js → chunk-HNY2FNJH.js} +1 -1
- package/dist/{chunk-OYDIND7Q.js → chunk-IMEJQQZU.js} +1 -1
- package/dist/{chunk-5KI5WVWS.js → chunk-KMK6AOB5.js} +95 -12
- package/dist/{chunk-LMI72WZP.js → chunk-WYCHM3EP.js} +8 -47
- package/dist/cli.js +5 -5
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-KYIQZBEO.js → intelligence-service-XPAKDZJI.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +12 -12
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
installSkills,
|
|
6
6
|
loadConfigRaw,
|
|
7
7
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HNY2FNJH.js";
|
|
9
9
|
import {
|
|
10
10
|
SKILL_MANIFEST_FILENAME,
|
|
11
11
|
SkillsClients
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IMEJQQZU.js";
|
|
13
13
|
|
|
14
14
|
// src/skills-autosync.ts
|
|
15
15
|
import fs from "fs";
|
|
@@ -16409,6 +16409,7 @@ export {
|
|
|
16409
16409
|
compileQueryClassifier,
|
|
16410
16410
|
MEASUREMENT_PLAN_V2_SCHEMA_VERSION,
|
|
16411
16411
|
measurementPlanV2Schema,
|
|
16412
|
+
canonicalMeasurementPlanV2,
|
|
16412
16413
|
canonicalMeasurementPlanV2Json,
|
|
16413
16414
|
measurementPlanV2ChecksumJson,
|
|
16414
16415
|
MEASUREMENT_PAGE_DEFAULT_LIMIT,
|
|
@@ -16748,7 +16749,6 @@ export {
|
|
|
16748
16749
|
siteCrawlDeadLinksResponseSchema,
|
|
16749
16750
|
SITE_AUDIT_DEFAULT_PAGE_LIMIT,
|
|
16750
16751
|
SITE_AUDIT_MAX_PAGE_LIMIT,
|
|
16751
|
-
SITE_AUDIT_DEFAULT_EDGE_LIMIT,
|
|
16752
16752
|
SITE_AUDIT_MAX_EDGE_LIMIT,
|
|
16753
16753
|
siteAuditRunRequestSchema,
|
|
16754
16754
|
normalizeSiteAuditRunRequest,
|
|
@@ -202,6 +202,7 @@ import {
|
|
|
202
202
|
calendarMonthBounds,
|
|
203
203
|
canonicalMeasurementExecutionIdentityJson,
|
|
204
204
|
canonicalMeasurementPlanJson,
|
|
205
|
+
canonicalMeasurementPlanV2,
|
|
205
206
|
canonicalMeasurementPlanV2Json,
|
|
206
207
|
canonicalizeAdsActivationManifest,
|
|
207
208
|
canonicalizeGoogleAdsCustomerSelection,
|
|
@@ -637,7 +638,7 @@ import {
|
|
|
637
638
|
wordpressSchemaDeployResultDtoSchema,
|
|
638
639
|
wordpressSchemaStatusResultDtoSchema,
|
|
639
640
|
wordpressStatusDtoSchema
|
|
640
|
-
} from "./chunk-
|
|
641
|
+
} from "./chunk-IMEJQQZU.js";
|
|
641
642
|
|
|
642
643
|
// src/intelligence-service.ts
|
|
643
644
|
import { eq as eq62, desc as desc27, asc as asc11, and as and51, ne as ne8, or as or14, inArray as inArray21, gte as gte14, lte as lte12, isNull as isNull9, sql as sql25, exists } from "drizzle-orm";
|
|
@@ -826,6 +827,17 @@ var measurementPlanVersions = sqliteTable("measurement_plan_versions", {
|
|
|
826
827
|
* never happened.
|
|
827
828
|
*/
|
|
828
829
|
compiledChecksum: text("compiled_checksum"),
|
|
830
|
+
/**
|
|
831
|
+
* Continuity link written at publish time: the superseded active version this
|
|
832
|
+
* revision is measurement-comparable with. Set ONLY when the publish changed
|
|
833
|
+
* nothing about execution — the frozen execution nodes of both revisions are
|
|
834
|
+
* canonically identical — so a run pinned to the linked version answered
|
|
835
|
+
* exactly the questions this revision would ask. A label-only republish
|
|
836
|
+
* therefore keeps serving the previous run instead of blanking the dashboard
|
|
837
|
+
* until the next sweep. Null for the first revision, for every
|
|
838
|
+
* execution-changing publish, and on every historic row.
|
|
839
|
+
*/
|
|
840
|
+
comparableToVersionId: text("comparable_to_version_id"),
|
|
829
841
|
publishedBy: text("published_by"),
|
|
830
842
|
sourceDraftId: text("source_draft_id"),
|
|
831
843
|
createdAt: text("created_at").notNull()
|
|
@@ -7039,6 +7051,21 @@ var MIGRATION_VERSIONS = [
|
|
|
7039
7051
|
`CREATE INDEX IF NOT EXISTS insight_notify_state_project
|
|
7040
7052
|
ON insight_notify_state(project_id)`
|
|
7041
7053
|
]
|
|
7054
|
+
},
|
|
7055
|
+
{
|
|
7056
|
+
version: 149,
|
|
7057
|
+
name: "measurement-plan-version-continuity",
|
|
7058
|
+
// Every measurement read pins to the active plan version row id, but a
|
|
7059
|
+
// publish mints a new row for ANY compiled-checksum change — labels
|
|
7060
|
+
// included — so renaming a group blanked the dashboard until the next full
|
|
7061
|
+
// sweep. This column records, at publish time, the superseded version a
|
|
7062
|
+
// cosmetic (execution-identical) revision stays comparable with, so reads
|
|
7063
|
+
// can keep serving the previous run. Historic rows stay NULL on purpose:
|
|
7064
|
+
// their execution equality was never verified at publish time, and
|
|
7065
|
+
// backfilling one would claim a comparison nobody made.
|
|
7066
|
+
statements: [
|
|
7067
|
+
`ALTER TABLE measurement_plan_versions ADD COLUMN comparable_to_version_id TEXT`
|
|
7068
|
+
]
|
|
7042
7069
|
}
|
|
7043
7070
|
];
|
|
7044
7071
|
function addRunsMeasurementPlanVersionForeignKey(tx) {
|
|
@@ -13258,10 +13285,37 @@ function responseFromReport(revision, report, run) {
|
|
|
13258
13285
|
diagnostics: report.diagnostics
|
|
13259
13286
|
};
|
|
13260
13287
|
}
|
|
13261
|
-
|
|
13288
|
+
var MEASUREMENT_COMPARABLE_VERSION_WALK_LIMIT = 32;
|
|
13289
|
+
function comparableMeasurementVersionIds(db, projectId, versionId) {
|
|
13290
|
+
const ids = [versionId];
|
|
13291
|
+
const seen = new Set(ids);
|
|
13292
|
+
let cursor = versionId;
|
|
13293
|
+
for (let step = 0; step < MEASUREMENT_COMPARABLE_VERSION_WALK_LIMIT; step++) {
|
|
13294
|
+
const row = db.select({ comparableToVersionId: measurementPlanVersions.comparableToVersionId }).from(measurementPlanVersions).where(and4(
|
|
13295
|
+
eq9(measurementPlanVersions.projectId, projectId),
|
|
13296
|
+
eq9(measurementPlanVersions.id, cursor)
|
|
13297
|
+
)).get();
|
|
13298
|
+
const next = row?.comparableToVersionId ?? null;
|
|
13299
|
+
if (next === null || seen.has(next)) break;
|
|
13300
|
+
ids.push(next);
|
|
13301
|
+
seen.add(next);
|
|
13302
|
+
cursor = next;
|
|
13303
|
+
}
|
|
13304
|
+
return ids;
|
|
13305
|
+
}
|
|
13306
|
+
function runVersionServesActiveVersion(db, projectId, activeVersionId, runVersionId) {
|
|
13307
|
+
if (runVersionId === null) return false;
|
|
13308
|
+
if (runVersionId === activeVersionId) return true;
|
|
13309
|
+
return comparableMeasurementVersionIds(db, projectId, activeVersionId).includes(runVersionId);
|
|
13310
|
+
}
|
|
13311
|
+
function latestMeasurementRun(db, projectId, versionId, statuses, window = {}, opts = {}) {
|
|
13262
13312
|
const conditions = [
|
|
13263
13313
|
eq9(runs.projectId, projectId),
|
|
13264
|
-
|
|
13314
|
+
// The revision-addressed report surface promises the revision AS-WAS and
|
|
13315
|
+
// must never borrow a predecessor's run through the comparable chain; the
|
|
13316
|
+
// active-dashboard surfaces want the chain so a label-only republish does
|
|
13317
|
+
// not blank them. exactVersion selects the contract.
|
|
13318
|
+
opts.exactVersion ? eq9(runs.measurementPlanVersionId, versionId) : inArray3(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, projectId, versionId)),
|
|
13265
13319
|
eq9(runs.kind, RunKinds["answer-visibility"]),
|
|
13266
13320
|
inArray3(runs.status, [...statuses]),
|
|
13267
13321
|
ne2(runs.trigger, RunTriggers.probe),
|
|
@@ -13271,11 +13325,11 @@ function latestMeasurementRun(db, projectId, versionId, statuses, window = {}) {
|
|
|
13271
13325
|
if (window.to !== void 0) conditions.push(lte2(runs.createdAt, window.to));
|
|
13272
13326
|
return db.select().from(runs).where(and4(...conditions)).orderBy(desc(runs.createdAt), desc(runs.id)).get();
|
|
13273
13327
|
}
|
|
13274
|
-
function pinnedMeasurementRun(db, projectId, versionId, runId) {
|
|
13328
|
+
function pinnedMeasurementRun(db, projectId, versionId, runId, opts = {}) {
|
|
13275
13329
|
return db.select().from(runs).where(and4(
|
|
13276
13330
|
eq9(runs.id, runId),
|
|
13277
13331
|
eq9(runs.projectId, projectId),
|
|
13278
|
-
eq9(runs.measurementPlanVersionId, versionId),
|
|
13332
|
+
opts.exactVersion ? eq9(runs.measurementPlanVersionId, versionId) : inArray3(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, projectId, versionId)),
|
|
13279
13333
|
eq9(runs.kind, RunKinds["answer-visibility"]),
|
|
13280
13334
|
inArray3(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
13281
13335
|
ne2(runs.trigger, RunTriggers.probe),
|
|
@@ -13287,7 +13341,7 @@ function measurementRunExpectedSlots(run, plan) {
|
|
|
13287
13341
|
return parseManifest(run.measurementManifest, frozenExecutionNodes(plan), run.measurementScope === null);
|
|
13288
13342
|
}
|
|
13289
13343
|
function storedMeasurementPlanV2Report(db, projectId, version, plan, runId) {
|
|
13290
|
-
const run = runId ? pinnedMeasurementRun(db, projectId, version.id, runId) : latestMeasurementRun(db, projectId, version.id, [RunStatuses.completed, RunStatuses.partial]);
|
|
13344
|
+
const run = runId ? pinnedMeasurementRun(db, projectId, version.id, runId, { exactVersion: true }) : latestMeasurementRun(db, projectId, version.id, [RunStatuses.completed, RunStatuses.partial], {}, { exactVersion: true });
|
|
13291
13345
|
if (!run) {
|
|
13292
13346
|
const empty = buildMeasurementPlanV2ReportInput(version.revision, plan, { schemaVersion: 1, expectedSlots: [] }, []);
|
|
13293
13347
|
return {
|
|
@@ -13321,7 +13375,7 @@ function buildStoredMeasurementReport(db, projectId, revision, runId) {
|
|
|
13321
13375
|
return storedMeasurementPlanV2Report(db, projectId, version, stored, runId);
|
|
13322
13376
|
}
|
|
13323
13377
|
const plan = stored;
|
|
13324
|
-
const run = runId ? pinnedMeasurementRun(db, projectId, version.id, runId) : db.select().from(runs).where(and4(
|
|
13378
|
+
const run = runId ? pinnedMeasurementRun(db, projectId, version.id, runId, { exactVersion: true }) : db.select().from(runs).where(and4(
|
|
13325
13379
|
eq9(runs.projectId, projectId),
|
|
13326
13380
|
eq9(runs.measurementPlanVersionId, version.id),
|
|
13327
13381
|
eq9(runs.kind, RunKinds["answer-visibility"]),
|
|
@@ -15908,6 +15962,26 @@ function diffCompiledPlans(active, candidate, activeRevision) {
|
|
|
15908
15962
|
}
|
|
15909
15963
|
};
|
|
15910
15964
|
}
|
|
15965
|
+
function plansAreLabelOnlyVariants(active, candidate) {
|
|
15966
|
+
const surface = (plan) => {
|
|
15967
|
+
const doc = canonicalMeasurementPlanV2(plan);
|
|
15968
|
+
const stripped = {
|
|
15969
|
+
...doc,
|
|
15970
|
+
// compiledChecksum is DERIVED over the full document, labels included,
|
|
15971
|
+
// so keeping it would smuggle the stripped labels back into the
|
|
15972
|
+
// comparison. Everything else in the doc is semantic and stays.
|
|
15973
|
+
compiledChecksum: "",
|
|
15974
|
+
targets: doc.targets.map((target) => ({ ...target, label: "" })),
|
|
15975
|
+
groups: doc.groups.map((group) => ({
|
|
15976
|
+
...group,
|
|
15977
|
+
label: "",
|
|
15978
|
+
competitors: group.competitors.map((competitor) => ({ ...competitor, label: "" }))
|
|
15979
|
+
}))
|
|
15980
|
+
};
|
|
15981
|
+
return JSON.stringify(canonicalJsonValue(stripped));
|
|
15982
|
+
};
|
|
15983
|
+
return surface(active) === surface(candidate);
|
|
15984
|
+
}
|
|
15911
15985
|
|
|
15912
15986
|
// ../api-routes/src/measurement-draft-actions.ts
|
|
15913
15987
|
var MEASUREMENT_DRAFT_ACTIONS = [
|
|
@@ -17366,7 +17440,10 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
17366
17440
|
const activeSchemaVersion = active ? active.schemaVersion === 2 ? 2 : 1 : null;
|
|
17367
17441
|
const completedRun = active ? app.db.select({ id: runs.id }).from(runs).where(and10(
|
|
17368
17442
|
eq15(runs.projectId, project.id),
|
|
17369
|
-
|
|
17443
|
+
// The comparable chain, not the bare active id: a label-only
|
|
17444
|
+
// republish must not flip setup back to awaiting_first_run while
|
|
17445
|
+
// the overview keeps serving the prior run.
|
|
17446
|
+
inArray5(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
|
|
17370
17447
|
eq15(runs.status, RunStatuses.completed)
|
|
17371
17448
|
)).get() : void 0;
|
|
17372
17449
|
const state = activeSchemaVersion === 1 ? "republish_required" : draft ? "setup_in_progress" : active ? completedRun ? "operational" : "awaiting_first_run" : "simple";
|
|
@@ -17774,6 +17851,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
17774
17851
|
createdAt: now.toISOString()
|
|
17775
17852
|
}).run();
|
|
17776
17853
|
}
|
|
17854
|
+
const comparableToVersionId = active !== null && active.schemaVersion === 2 && plansAreLabelOnlyVariants(parseV2Plan(active), compiled.plan) ? active.id : null;
|
|
17777
17855
|
tx.insert(measurementPlanVersions).values({
|
|
17778
17856
|
id: versionId,
|
|
17779
17857
|
projectId: gate.project.id,
|
|
@@ -17782,6 +17860,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
17782
17860
|
checksum: sha256Hex(canonicalJson3),
|
|
17783
17861
|
schemaVersion: 2,
|
|
17784
17862
|
compiledChecksum: compiled.plan.compiledChecksum,
|
|
17863
|
+
comparableToVersionId,
|
|
17785
17864
|
publishedBy: serializeActor(gate.actor),
|
|
17786
17865
|
sourceDraftId: row.id,
|
|
17787
17866
|
createdAt: now.toISOString()
|
|
@@ -18947,7 +19026,7 @@ function selectDisplayedRun(db, projectId, active, query) {
|
|
|
18947
19026
|
}
|
|
18948
19027
|
const run = db.select().from(runs).where(and12(eq18(runs.projectId, projectId), eq18(runs.id, selectedRunId))).get();
|
|
18949
19028
|
if (!run) throw notFound("Run", selectedRunId);
|
|
18950
|
-
if (
|
|
19029
|
+
if (runVersionServesActiveVersion(db, projectId, active.version.id, run.measurementPlanVersionId)) return run;
|
|
18951
19030
|
const pinned = run.measurementPlanVersionId === null ? null : db.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq18(measurementPlanVersions.id, run.measurementPlanVersionId)).get()?.revision ?? null;
|
|
18952
19031
|
throw runRevisionMismatch(run.id, pinned, active.version.revision);
|
|
18953
19032
|
}
|
|
@@ -19288,7 +19367,7 @@ function selectDisplayedRun2(db, projectId, active, runId) {
|
|
|
19288
19367
|
}
|
|
19289
19368
|
const run = db.select().from(runs).where(and13(eq19(runs.projectId, projectId), eq19(runs.id, runId))).get();
|
|
19290
19369
|
if (!run) throw notFound("Run", runId);
|
|
19291
|
-
if (
|
|
19370
|
+
if (runVersionServesActiveVersion(db, projectId, active.version.id, run.measurementPlanVersionId)) return run;
|
|
19292
19371
|
const pinned = run.measurementPlanVersionId === null ? null : db.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq19(measurementPlanVersions.id, run.measurementPlanVersionId)).get()?.revision ?? null;
|
|
19293
19372
|
throw runRevisionMismatch(run.id, pinned, active.version.revision);
|
|
19294
19373
|
}
|
|
@@ -19487,7 +19566,7 @@ function selectMeasurementQuestionRun(db, projectId, active, runId) {
|
|
|
19487
19566
|
eq20(runs.projectId, projectId)
|
|
19488
19567
|
)).get();
|
|
19489
19568
|
if (!run) throw notFound("Run", runId);
|
|
19490
|
-
if (
|
|
19569
|
+
if (!runVersionServesActiveVersion(db, projectId, active.version.id, run.measurementPlanVersionId)) {
|
|
19491
19570
|
const pinned = run.measurementPlanVersionId === null ? null : db.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq20(measurementPlanVersions.id, run.measurementPlanVersionId)).get()?.revision ?? null;
|
|
19492
19571
|
throw runRevisionMismatch(run.id, pinned, active.version.revision);
|
|
19493
19572
|
}
|
|
@@ -20179,7 +20258,11 @@ function previousComparableRun(db, active, current) {
|
|
|
20179
20258
|
measurementExecutionIdentity: runs.measurementExecutionIdentity
|
|
20180
20259
|
}).from(runs).where(and15(
|
|
20181
20260
|
eq21(runs.projectId, current.projectId),
|
|
20182
|
-
|
|
20261
|
+
// The comparable chain keeps period-over-period alive across a label-only
|
|
20262
|
+
// republish: a run pinned to a comparable prior revision measured exactly
|
|
20263
|
+
// the questions the active revision asks. The execution-identity and scope
|
|
20264
|
+
// checks below still gate what actually compares.
|
|
20265
|
+
inArray7(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
|
|
20183
20266
|
eq21(runs.kind, RunKinds["answer-visibility"]),
|
|
20184
20267
|
inArray7(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
20185
20268
|
or3(
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
loadConfig,
|
|
12
12
|
loadConfigRaw,
|
|
13
13
|
saveConfigPatch
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HNY2FNJH.js";
|
|
15
15
|
import {
|
|
16
16
|
CC_CACHE_DIR,
|
|
17
17
|
DUCKDB_SPEC,
|
|
@@ -157,7 +157,7 @@ import {
|
|
|
157
157
|
siteCrawlSnapshots,
|
|
158
158
|
toAlertView,
|
|
159
159
|
usageCounters
|
|
160
|
-
} from "./chunk-
|
|
160
|
+
} from "./chunk-KMK6AOB5.js";
|
|
161
161
|
import {
|
|
162
162
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
163
163
|
AGENT_PROVIDER_IDS,
|
|
@@ -191,7 +191,6 @@ import {
|
|
|
191
191
|
RunKinds,
|
|
192
192
|
RunStatuses,
|
|
193
193
|
RunTriggers,
|
|
194
|
-
SITE_AUDIT_DEFAULT_EDGE_LIMIT,
|
|
195
194
|
SITE_AUDIT_DEFAULT_PAGE_LIMIT,
|
|
196
195
|
SITE_AUDIT_MAX_EDGE_LIMIT,
|
|
197
196
|
SITE_AUDIT_MAX_PAGE_LIMIT,
|
|
@@ -296,7 +295,7 @@ import {
|
|
|
296
295
|
validationError,
|
|
297
296
|
winnabilityClassLabel,
|
|
298
297
|
withRetry
|
|
299
|
-
} from "./chunk-
|
|
298
|
+
} from "./chunk-IMEJQQZU.js";
|
|
300
299
|
|
|
301
300
|
// src/telemetry.ts
|
|
302
301
|
import crypto from "crypto";
|
|
@@ -10742,7 +10741,7 @@ function clampSiteAuditLimit(limit) {
|
|
|
10742
10741
|
return Math.max(1, Math.min(SITE_AUDIT_MAX_PAGE_LIMIT, Math.floor(limit)));
|
|
10743
10742
|
}
|
|
10744
10743
|
function clampSiteAuditEdgeLimit(limit) {
|
|
10745
|
-
if (limit == null || !Number.isFinite(limit)) return
|
|
10744
|
+
if (limit == null || !Number.isFinite(limit)) return void 0;
|
|
10746
10745
|
return Math.max(1, Math.min(SITE_AUDIT_MAX_EDGE_LIMIT, Math.floor(limit)));
|
|
10747
10746
|
}
|
|
10748
10747
|
function toPageFactor(factor) {
|
|
@@ -10873,43 +10872,6 @@ function deadLinkCheckedCount(edges, pages) {
|
|
|
10873
10872
|
}
|
|
10874
10873
|
return new Set([...edges].filter((edge) => edge.type === "anchor" && edge.classification === "internal" && attemptedUrls.has(edge.to)).map((edge) => edge.to)).size;
|
|
10875
10874
|
}
|
|
10876
|
-
var RATE_LIMITED_STATUS = 429;
|
|
10877
|
-
function partitionDeadLinks(deadLinks) {
|
|
10878
|
-
const reported = deadLinks.findings;
|
|
10879
|
-
const engineUnverified = deadLinks.unverified ?? [];
|
|
10880
|
-
const answeredWithError = (finding) => typeof finding.statusCode === "number" && finding.statusCode >= 400;
|
|
10881
|
-
const dead = reported.filter((finding) => answeredWithError(finding) && finding.statusCode !== RATE_LIMITED_STATUS);
|
|
10882
|
-
const unverified = [
|
|
10883
|
-
...reported.filter((finding) => !answeredWithError(finding) || finding.statusCode === RATE_LIMITED_STATUS),
|
|
10884
|
-
...engineUnverified
|
|
10885
|
-
];
|
|
10886
|
-
return { dead, unverified };
|
|
10887
|
-
}
|
|
10888
|
-
function reportedTermination(summary) {
|
|
10889
|
-
const limits = summary.limits;
|
|
10890
|
-
if (limits) {
|
|
10891
|
-
if (limits.maxBytes && (summary.bytesRead ?? 0) >= limits.maxBytes) return "max-bytes";
|
|
10892
|
-
if (limits.maxDurationMs && (summary.elapsedMs ?? 0) >= limits.maxDurationMs) return "max-duration";
|
|
10893
|
-
if (limits.maxFetches && (summary.fetchesStarted ?? 0) >= limits.maxFetches) return "max-fetches";
|
|
10894
|
-
}
|
|
10895
|
-
return summary.terminationReason ?? "complete";
|
|
10896
|
-
}
|
|
10897
|
-
function crawlBudgetsFor(maxPages) {
|
|
10898
|
-
return {
|
|
10899
|
-
// 2x the ~745 KB/page measured on a media-heavy production site, so the
|
|
10900
|
-
// byte cap is headroom rather than the thing that stops the crawl.
|
|
10901
|
-
maxBytes: maxPages * 15e5,
|
|
10902
|
-
// ~5 pages/s at the engine's default concurrency of 5, doubled for slow
|
|
10903
|
-
// origins, and never below the engine's own 2-minute floor.
|
|
10904
|
-
maxDurationMs: Math.max(12e4, Math.ceil(maxPages / 5 * 1e3 * 2)),
|
|
10905
|
-
// Redirects and dead-link probes cost fetches without producing pages.
|
|
10906
|
-
maxFetches: Math.ceil(maxPages * 1.5),
|
|
10907
|
-
// Raised off the default of 10 because it is an ADMISSION limit: a sitemap
|
|
10908
|
-
// with many query-parameter variants trips it during seeding and latches a
|
|
10909
|
-
// soft reason that then masks whatever really stops the crawl.
|
|
10910
|
-
maxQueryVariants: Math.max(50, Math.ceil(maxPages / 10))
|
|
10911
|
-
};
|
|
10912
|
-
}
|
|
10913
10875
|
async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
10914
10876
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10915
10877
|
const claim = db.update(runs).set({ status: "running", startedAt }).where(and12(eq15(runs.id, runId), eq15(runs.projectId, projectId), eq15(runs.status, "queued"))).run();
|
|
@@ -11210,7 +11172,6 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11210
11172
|
maxEdges,
|
|
11211
11173
|
maxDepth: opts.maxDepth ?? null
|
|
11212
11174
|
});
|
|
11213
|
-
const budgets = crawlBudgetsFor(maxPages);
|
|
11214
11175
|
const report = await runSiteCrawl(crawlRootUrl, {
|
|
11215
11176
|
mode: "summary",
|
|
11216
11177
|
sitemapUrl: opts.sitemapUrl,
|
|
@@ -11218,7 +11179,6 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11218
11179
|
maxEdges,
|
|
11219
11180
|
maxDepth: opts.maxDepth,
|
|
11220
11181
|
checkDeadLinks: opts.checkDeadLinks ?? false,
|
|
11221
|
-
...budgets,
|
|
11222
11182
|
signal: opts.signal,
|
|
11223
11183
|
onEvent: persistEvent
|
|
11224
11184
|
});
|
|
@@ -11253,7 +11213,8 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11253
11213
|
const errorCount = observedErrorCount(observedPages.values());
|
|
11254
11214
|
const terminalStatus = crawlSummary.complete ? "completed" : "partial";
|
|
11255
11215
|
const deadLinksChecked = opts.checkDeadLinks ? deadLinkCheckedCount(observedEdges.values(), observedPages.values()) : 0;
|
|
11256
|
-
const
|
|
11216
|
+
const deadLinkFindings = report.deadLinks.findings;
|
|
11217
|
+
const unverifiedLinks = report.deadLinks.unverified;
|
|
11257
11218
|
const deadLinksFound = deadLinkFindings.length;
|
|
11258
11219
|
const deadLinksUnverified = new Set(unverifiedLinks.map((finding) => finding.to)).size;
|
|
11259
11220
|
const legacyIssues = factors.map((factor) => toLegacyIssue(factor, crawlSummary.auditRollup.auditedPages)).filter((issue) => issue !== null);
|
|
@@ -11345,7 +11306,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11345
11306
|
maxDepth: opts.maxDepth ?? null,
|
|
11346
11307
|
checkDeadLinks: opts.checkDeadLinks ?? false,
|
|
11347
11308
|
complete: crawlSummary.complete,
|
|
11348
|
-
termination:
|
|
11309
|
+
termination: crawlSummary.terminationReason ?? "complete",
|
|
11349
11310
|
detailsAvailable: true,
|
|
11350
11311
|
pagesDiscovered: crawlSummary.pagesDiscovered,
|
|
11351
11312
|
pagesFetched: crawlSummary.pagesFetched,
|
|
@@ -11896,7 +11857,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
11896
11857
|
return result;
|
|
11897
11858
|
}
|
|
11898
11859
|
async function backfillInsightsCommand(project, opts) {
|
|
11899
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
11860
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-XPAKDZJI.js");
|
|
11900
11861
|
const config = loadConfig();
|
|
11901
11862
|
const db = createClient(config.database);
|
|
11902
11863
|
migrate(db);
|
package/dist/cli.js
CHANGED
|
@@ -26,11 +26,11 @@ import {
|
|
|
26
26
|
showFirstRunNotice,
|
|
27
27
|
trackCliCommandFinished,
|
|
28
28
|
trackEvent
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-WYCHM3EP.js";
|
|
30
30
|
import {
|
|
31
31
|
autoSyncSkills,
|
|
32
32
|
formatAutoSyncNotice
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-EBRGLDTB.js";
|
|
34
34
|
import {
|
|
35
35
|
CliError,
|
|
36
36
|
EXIT_SYSTEM_ERROR,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
saveConfigPatch,
|
|
56
56
|
systemError,
|
|
57
57
|
usageError
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-HNY2FNJH.js";
|
|
59
59
|
import {
|
|
60
60
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
61
61
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -69,7 +69,7 @@ import {
|
|
|
69
69
|
projects,
|
|
70
70
|
queries,
|
|
71
71
|
renderReportHtml
|
|
72
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-KMK6AOB5.js";
|
|
73
73
|
import {
|
|
74
74
|
AdsDeliverySnapshotStatuses,
|
|
75
75
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -138,7 +138,7 @@ import {
|
|
|
138
138
|
providerQuotaPolicySchema,
|
|
139
139
|
resolveProviderInput,
|
|
140
140
|
winnabilityClassSchema
|
|
141
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-IMEJQQZU.js";
|
|
142
142
|
|
|
143
143
|
// src/cli.ts
|
|
144
144
|
import { pathToFileURL } from "url";
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WYCHM3EP.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-HNY2FNJH.js";
|
|
10
|
+
import "./chunk-KMK6AOB5.js";
|
|
11
|
+
import "./chunk-IMEJQQZU.js";
|
|
12
12
|
export {
|
|
13
13
|
GoogleMarketingRuntimeError,
|
|
14
14
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EBRGLDTB.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HNY2FNJH.js";
|
|
8
8
|
import {
|
|
9
9
|
isReadOnlyKey
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IMEJQQZU.js";
|
|
11
11
|
|
|
12
12
|
// src/mcp/cli.ts
|
|
13
13
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.178.
|
|
3
|
+
"version": "4.178.4",
|
|
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
|
"license": "FSL-1.1-ALv2",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@anthropic-ai/sdk": "^0.91.1",
|
|
44
|
-
"@canonry/aeo-audit": "
|
|
44
|
+
"@canonry/aeo-audit": "7.1.0",
|
|
45
45
|
"@fastify/rate-limit": "^11.2.0",
|
|
46
46
|
"@fastify/static": "^9.1.1",
|
|
47
47
|
"@google/genai": "^1.46.0",
|
|
@@ -71,30 +71,30 @@
|
|
|
71
71
|
"tsup": "^8.5.1",
|
|
72
72
|
"tsx": "^4.19.0",
|
|
73
73
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
75
74
|
"@ainyc/canonry-config": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
77
75
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
78
|
-
"@ainyc/canonry-
|
|
76
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
77
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
79
78
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
79
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
80
80
|
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
81
81
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
82
82
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
83
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
84
83
|
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
85
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
86
84
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
87
|
-
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
88
85
|
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
86
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
87
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
88
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
89
89
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
90
90
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
91
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
91
92
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
92
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
93
93
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
94
|
-
"@ainyc/canonry-provider-
|
|
94
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
95
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
95
96
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
96
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
97
|
-
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
97
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
98
98
|
},
|
|
99
99
|
"scripts": {
|
|
100
100
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|