@canonry/canonry 7.78.3 → 7.79.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.
Files changed (44) hide show
  1. package/assets/agent-workspace/skills/aero/references/agent-operations.md +6 -0
  2. package/assets/agent-workspace/skills/canonry/SKILL.md +6 -0
  3. package/assets/assets/{AgentSetupPage-BGdvyQFL.js → AgentSetupPage-Cr2ZU_4s.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-CwPuJMBy.js → MeasurementPropertyPage-ighxjOiq.js} +1 -1
  5. package/assets/assets/{ProjectPage-Bbnbg7c9.js → ProjectPage-DnAXCPle.js} +2 -2
  6. package/assets/assets/{RunsPage-CJHJ7kHk.js → RunsPage-Ds5K3fOQ.js} +1 -1
  7. package/assets/assets/{SettingsPage-r8VrtFyJ.js → SettingsPage-B8Jed-xH.js} +1 -1
  8. package/assets/assets/{SiteHealthSection-D1oSuo9O.js → SiteHealthSection-cjNQasWj.js} +2 -2
  9. package/assets/assets/{TrafficPage-DY2ykwH1.js → TrafficPage-BUid1rkh.js} +1 -1
  10. package/assets/assets/{index-Dfm8z5cG.js → index-BhoSVTom.js} +3 -3
  11. package/assets/assets/index-TBDfE2OO.css +1 -0
  12. package/assets/assets/{react-sigma_core.esm.min-Bjdtl0TQ.js → react-sigma_core.esm.min-SbOH7c6K.js} +1 -1
  13. package/assets/index.html +2 -2
  14. package/dist/{backfill-IRVLT6VT.js → backfill-SRE52FDL.js} +4 -4
  15. package/dist/{bootstrap-WZ6YDQIG.js → bootstrap-ITVA7X45.js} +1 -1
  16. package/dist/{chunk-OES6PSQK.js → chunk-27MGZQ6Z.js} +23 -41
  17. package/dist/{chunk-7HE4LAJY.js → chunk-6OCQTAXU.js} +16 -9
  18. package/dist/{chunk-5NBXPO4G.js → chunk-7S6SQFFT.js} +1 -1
  19. package/dist/{chunk-KHIZSTDP.js → chunk-DEQC5XVD.js} +15 -15
  20. package/dist/{chunk-PH4AESRE.js → chunk-HRFPGXON.js} +18 -0
  21. package/dist/{chunk-IYMTQHPD.js → chunk-I7RTAHCL.js} +1 -1
  22. package/dist/{chunk-WVCDUKJ2.js → chunk-JI7FDO7I.js} +19 -0
  23. package/dist/{chunk-PRCBHOVR.js → chunk-KUMHO22S.js} +15 -8
  24. package/dist/{chunk-LBNUTWPK.js → chunk-OIRHCT63.js} +1 -1
  25. package/dist/{chunk-QALET4XH.js → chunk-QOKK5PMO.js} +10 -10
  26. package/dist/{chunk-BKOG3GEI.js → chunk-RPTOVEZT.js} +79 -9
  27. package/dist/{chunk-LOMRNRML.js → chunk-SWWZ733W.js} +2 -2
  28. package/dist/{chunk-BTMLE3EN.js → chunk-ZMMS3FAR.js} +2 -2
  29. package/dist/{cli-commands-6M5QDGBZ.js → cli-commands-BZLUMYKR.js} +1 -1
  30. package/dist/cli.js +2 -2
  31. package/dist/{dashboard-6MMYA2GG.js → dashboard-43ST35IW.js} +2 -2
  32. package/dist/{demo-3R2SHQPO.js → demo-COMFIESH.js} +1 -1
  33. package/dist/{demo-server-ISJOEJN5.js → demo-server-MRGL3SNP.js} +4 -4
  34. package/dist/index.d.ts +16 -144
  35. package/dist/index.js +10 -10
  36. package/dist/{init-FLWVOJHU.js → init-YKLLVT7X.js} +2 -2
  37. package/dist/{intelligence-service-MPNONLCW.js → intelligence-service-5STL6A45.js} +3 -3
  38. package/dist/mcp.js +2 -2
  39. package/dist/{serve-7HN3VT6J.js → serve-VU3E7XTX.js} +11 -11
  40. package/dist/{session-FBHHWILQ.js → session-JKMEKQYL.js} +7 -6
  41. package/dist/{src-AQ5MHQGQ.js → src-QC2VNJWJ.js} +3 -1
  42. package/dist/{tools-3ACR2D2V.js → tools-LGTWLH5Y.js} +3 -3
  43. package/package.json +1 -1
  44. package/assets/assets/index-CHHZDc6d.css +0 -1
@@ -27,14 +27,14 @@ import {
27
27
  resolveConfiguredAgentProvider,
28
28
  resolveSessionProviderAndModel,
29
29
  setAeroSystemPrompt
30
- } from "./chunk-OES6PSQK.js";
30
+ } from "./chunk-27MGZQ6Z.js";
31
31
  import {
32
32
  AeroToolProfiles,
33
33
  AeroToolScopes,
34
34
  buildAeroStateTools,
35
35
  isAeroToolProfile,
36
36
  truncateToolResult
37
- } from "./chunk-IYMTQHPD.js";
37
+ } from "./chunk-I7RTAHCL.js";
38
38
  import {
39
39
  getGoogleAuthConfig,
40
40
  getGoogleConnection,
@@ -64,7 +64,7 @@ import {
64
64
  openaiAdapter,
65
65
  openrouterAdapter,
66
66
  perplexityAdapter
67
- } from "./chunk-5NBXPO4G.js";
67
+ } from "./chunk-7S6SQFFT.js";
68
68
  import {
69
69
  classifyUsageSurface,
70
70
  createApiUsageTelemetry,
@@ -99,11 +99,11 @@ import {
99
99
  } from "./chunk-4GEEYY3N.js";
100
100
  import {
101
101
  createCanonryMcpServer
102
- } from "./chunk-BKOG3GEI.js";
102
+ } from "./chunk-RPTOVEZT.js";
103
103
  import {
104
104
  CANONRY_MCP_TIERS,
105
105
  CANONRY_MCP_TOOLKIT_NAMES
106
- } from "./chunk-WVCDUKJ2.js";
106
+ } from "./chunk-JI7FDO7I.js";
107
107
  import {
108
108
  ApiClient
109
109
  } from "./chunk-7OAXEMOF.js";
@@ -148,7 +148,7 @@ import {
148
148
  persistSiteCrawlGraphLayout,
149
149
  prepareSiteCrawlGraphLayout,
150
150
  recordedSharePct
151
- } from "./chunk-LBNUTWPK.js";
151
+ } from "./chunk-OIRHCT63.js";
152
152
  import {
153
153
  CanonryMcpToolNames,
154
154
  canonryMcpTools
@@ -161,7 +161,7 @@ import {
161
161
  } from "./chunk-HGMYEDAQ.js";
162
162
  import {
163
163
  IntelligenceService
164
- } from "./chunk-BTMLE3EN.js";
164
+ } from "./chunk-ZMMS3FAR.js";
165
165
  import {
166
166
  addLogListener,
167
167
  createFastifyLogger,
@@ -291,7 +291,7 @@ import {
291
291
  webhookResponseReason,
292
292
  webhookTargetRefusalReason,
293
293
  writeAuditLog
294
- } from "./chunk-PRCBHOVR.js";
294
+ } from "./chunk-KUMHO22S.js";
295
295
  import {
296
296
  OperationalLogStore,
297
297
  SentimentIdempotencyConflict,
@@ -377,7 +377,7 @@ import {
377
377
  siteLivenessState,
378
378
  trafficSources,
379
379
  usageCounters
380
- } from "./chunk-PH4AESRE.js";
380
+ } from "./chunk-HRFPGXON.js";
381
381
  import {
382
382
  AGENT_MEMORY_VALUE_MAX_BYTES,
383
383
  AI_ENGINE_DOMAINS,
@@ -5937,7 +5937,7 @@ function nonBlank(value) {
5937
5937
  return trimmed ? trimmed : void 0;
5938
5938
  }
5939
5939
  function resolveBuildCommit(env = process.env) {
5940
- const embedded = true ? "d3a929f13cf172d1ad099aa143935239e90409d1" : void 0;
5940
+ const embedded = true ? "7d17991013508621d89f3b6ce69a1ea77ae372ad" : void 0;
5941
5941
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
5942
5942
  }
5943
5943
  function resolveInstanceIdentity(env = process.env) {
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  CANONRY_MCP_TOOLKITS,
3
3
  CANONRY_MCP_TOOLKIT_NAMES,
4
- isCanonryMcpToolkitName
5
- } from "./chunk-WVCDUKJ2.js";
4
+ isCanonryMcpToolkitName,
5
+ resolveAeroSkillDir
6
+ } from "./chunk-JI7FDO7I.js";
6
7
  import {
7
8
  createApiClient,
8
9
  runWithUsageTags
@@ -125,8 +126,8 @@ function formatZodIssue(issue) {
125
126
  function zodErrorMessage(error) {
126
127
  const first = error.issues[0];
127
128
  if (!first) return "Input validation failed";
128
- const path = first.path.map(String).join(".");
129
- return path ? `${path}: ${first.message}` : first.message;
129
+ const path2 = first.path.map(String).join(".");
130
+ return path2 ? `${path2}: ${first.message}` : first.message;
130
131
  }
131
132
 
132
133
  // src/mcp/dynamic-catalog.ts
@@ -239,6 +240,8 @@ var OPERATIONS_GUIDE = {
239
240
  ],
240
241
  "approvalRule": "Get explicit approval for the exact target, action, and bounded provider work before crossing a boundary. Existing approval covers only its stated scope; stop on refusal or ambiguous results.",
241
242
  "authority": "Guidance and tool visibility are not permission grants. Server-side roles, scopes, project boundaries, quotas, and approval receipts remain authoritative. Never bypass a refusal with different credentials or endpoints.",
243
+ "playbookRule": 'Read each listed playbook with canonry_help({playbook:"<slug>"}) before interpreting results.',
244
+ "playbookNote": `Shared with Canonry's built-in agent and CLI hosts. Where it names aero_* tools, read_skill_doc or shell cnry commands, use the matching canonry_* tool on this connection. Read a reference it names (references/<slug>.md) with canonry_help({playbook:"<slug>"}). Playbooks are guidance, not permission.`,
242
245
  "workflows": {
243
246
  "seo": {
244
247
  "keywords": [
@@ -258,6 +261,9 @@ var OPERATIONS_GUIDE = {
258
261
  "canonry_seo_sync",
259
262
  "canonry_seo_run_cancel"
260
263
  ],
264
+ "playbooks": [
265
+ "seo-analysis"
266
+ ],
261
267
  "guidance": "Read saved SEO evidence first. Preserve profile, exact domain or host, market, language, plan revision, dataset and collection date. Market rankings (canonry_seo_market_rankings) are the site's Google position for its tracked queries by market, the same queries AI visibility measures; start with canonry_seo_market_summary for counts by outcome, and treat failed or unsearched queries as missing data. SEO traffic and keyword metrics are third-party estimates, separate from Search Console observations and AI citation and mention coverage. Refresh requires explicit approval for the profile and work, a fresh refresh intent and an idempotency key. Hosted financial controls are internal; no credential or billing information belongs in the response."
262
268
  },
263
269
  "operations": {
@@ -288,6 +294,9 @@ var OPERATIONS_GUIDE = {
288
294
  "canonry_projects_list",
289
295
  "canonry_project_overview"
290
296
  ],
297
+ "playbooks": [
298
+ "aero"
299
+ ],
291
300
  "guidance": "Read canonry_status first for stored integration health, freshness, and repeated failures across accessible projects, then inspect a project overview for detail. Report missing evidence; do not start a sweep or sync to fill a gap."
292
301
  },
293
302
  "diagnose": {
@@ -304,6 +313,10 @@ var OPERATIONS_GUIDE = {
304
313
  "canonry_project_overview",
305
314
  "canonry_project_history"
306
315
  ],
316
+ "playbooks": [
317
+ "aero",
318
+ "regression-playbook"
319
+ ],
307
320
  "guidance": "Compare stored history in the same project, period, provider/model, location, and query-class scope. Separate observed changes from possible causes; propose any live verification for approval."
308
321
  },
309
322
  "prospecting": {
@@ -338,6 +351,10 @@ var OPERATIONS_GUIDE = {
338
351
  "canonry_measurement_setup",
339
352
  "canonry_research_runs_list"
340
353
  ],
354
+ "playbooks": [
355
+ "portfolio-analysis",
356
+ "aeo-discovery"
357
+ ],
341
358
  "guidance": "Inspect existing measurement before editing it. Preserve Simple versus Advanced scope, Property/Target identity, market, provider/model, and query class. Direct research submits final queries in one context; reviewed batches submit explicit destinations under one retry key. Expand patterns client-side: scope records a destination and never rewrites queries or fans out a group. Research is separate from tracking; publication does not authorize a sweep."
342
359
  },
343
360
  "integrations": {
@@ -359,6 +376,9 @@ var OPERATIONS_GUIDE = {
359
376
  "canonry_ga_status",
360
377
  "canonry_google_ads_status"
361
378
  ],
379
+ "playbooks": [
380
+ "ai-traffic-tracking"
381
+ ],
362
382
  "guidance": "Read canonry_status first for the stored instance or project health view, then use specialist tools for detail. Connecting, selecting resources, syncing, and live provider reads require scoped approval; never request credentials in chat."
363
383
  },
364
384
  "reports": {
@@ -373,14 +393,18 @@ var OPERATIONS_GUIDE = {
373
393
  "canonry_project_overview",
374
394
  "canonry_organic_evidence"
375
395
  ],
396
+ "playbooks": [
397
+ "aero",
398
+ "reporting"
399
+ ],
376
400
  "guidance": "Build the requested summary from stored project overview, organic evidence, and the relevant visibility, measurement, integration, or traffic reads. Retain evidence dates, scope, sample sizes, missing data, and separate mention/citation signals; do not generate fresh runs implicitly."
377
401
  }
378
402
  },
379
- "markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `operations`, `prospecting`, `measurement`, `integrations`,\n`reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Setup:** Page Health needs no answer-engine provider; AI Visibility does.\nAfter a Page Health result on an install with no provider (a `NO_PROVIDER`\nnotice, or doctor's `providers.none-configured`), propose AI Visibility setup\nas the next step. The operator adds the provider key in the dashboard or in\ntheir own terminal; never ask for it in chat.\nRerunning `canonry bootstrap` after a provider change reloads saved provider\nsettings on a matching running local server and reports whether they became\nactive. If the server is offline, start it to apply the saved settings. For an\nexplicit reload of the connected server's own config, use\n`canonry settings reload-providers` or `canonry_providers_reload` with install\nadministrator authority. Remote servers are never reloaded automatically by\nbootstrap, and a local server that belongs to another install is left alone.\nPorts and database settings still need a restart.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Site Health:** read `canonry_site_health_issues` for stored technical findings,\naffected-page counts and example URLs, then `canonry_site_health_issue_pages`\nfor a selected issue's remaining pages. Pin subsequent reads to the returned\nrun. Inspect coverage and omissions: a passing score can still have findings,\nan older scan may lack cross-page evidence, and a partial scan cannot establish\nsite-wide absence. Advisory findings require judgment before proposing a repair.\nAudit evidence informs technical repairs and existing-page recommendations;\nit does not itself establish a new-blog opportunity or authorize any edit.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Compact `nextCursor` completes only `pageList`; use `list` to enumerate\none ranking, markets, observed names or cited domains, preserving filters.\nFirst-page sibling lists are bounded summaries. Keep sample sizes and ties\nvisible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\n### Agent operations\n\nUse `canonry_key_self` (CLI `canonry key whoami --format json`) to inspect the\ncurrent credential's scopes, project boundary, and host-derived `operator`\nauthority without exposing its token. Missing `operator` means unapproved.\n`canonry_settings_get` and\n`canonry_telemetry_get` describe the connected server, not the agent's local\nmachine. Telemetry reports configured preference, effective state, and any\nenvironment override; inspecting status never creates an anonymous identifier.\nAfter approval, `canonry_telemetry_update` changes that preference and\n`canonry_provider_settings_update` changes an already-configured provider's\nmodel/quota. Both require `settings.write`; neither accepts credentials.\nServer telemetry reads and updates additionally require operator authority.\nOrdinary audit-history reads omit internal telemetry events and their state.\n\nOperator authority is deny-by-default and separate from customer admin roles.\nThe deployment owner must approve a dedicated, instance-wide API key's ID in\nthe server environment variable `CANONRY_OPERATOR_KEY_IDS` (comma-separated IDs),\nthen restart the server. Empty/unset approves nobody; wildcards are invalid.\nKeep the bearer private to internal operators; never approve a customer-held or\nshared proxy/bootstrap key. Use `logs.read` for read-only diagnostics, adding\n`settings.write` only when telemetry control is required. Ordinary key creation,\naccount roles, OAuth consent, and caller headers cannot grant operator status.\nRevoking an approved key invalidates it immediately. Host enrollment is a trust\nbootstrap step, intentionally unavailable through customer-facing APIs.\nAPI, CLI, and MCP enforce the same boundary; MCP hides internal tools unless\nthe server confirms operator authority, including in explicit read-only mode.\nProject analytics, research, and normal project permissions are unchanged.\n\n`canonry_logs_list` reads bounded, redacted runtime events from both the\napplication logger and Fastify request/error logging. It requires an\ninstance-wide `logs.read` grant (or wildcard) and a host-approved direct bearer.\nBrowser sessions, OAuth/delegated credentials, customer admins, and project-scoped\nkeys cannot use it, even with a project filter or a matching allowlist ID.\nA `logs.read`-only key is read-only automatically, without a\nsecond `read` marker. Named `*.read` scopes cannot grant mutations; an explicit\nwrite grant is needed and remains subject to its route gates. Returned messages\nare sanitized and bounded; raw request or response bodies, headers, cookies,\nprovider payloads, and stacks are not\npart of the queryable surface. The same secret-redaction policy runs before\nconsole output and storage. Do not deliberately log secrets: redaction is a\ndefense in depth, not permission to put credentials into diagnostic strings.\nOpaque escaped payloads containing secret assignments are omitted when safe\npartial masking cannot be guaranteed; correlate their retained error codes and IDs.\n\nFile-backed hosts retain runtime logs in SQLite across restarts, bounded to\n10,000 events and seven days. In-memory hosts report `retention: \"process\"`.\nFilter by `actor`, `requestId`, `runId`, `projectId`, `module`, `level`, or an\ninclusive `since`/`until` interval. Keep filters unchanged when resuming an\nopaque cursor; retention eviction can invalidate it. Inspect `retentionPolicy`,\n`captureErrors`, `dropped`, `truncated`, and `retention` before drawing\nconclusions. Missing logs are not proof that an action did not happen. Use\n`canonry_project_history` or `canonry_history_global` for persistent audit events;\noffset pages have deterministic ordering but are not snapshots of concurrent writes.\n\nAudit `actor` comes from authenticated identity (`user:<id>` or `api-key:<id>`),\nnot a caller-supplied header. A delegated MCP credential records its originating\nuser as actor and the actual credential in `credentialId`. `requestId` correlates\nHTTP events; `userAgent` and `actorSession` are bounded, untrusted client hints,\nnever identity or permission grants. Older audit rows are not backfilled with\nidentities the server cannot prove.\n\nBoth shipped HTTP hosts issue restart-safe UUID request IDs and return them in\n`x-request-id`. Use that value to correlate a CLI/API failure with log entries;\nHTTP diagnostics retain the method and route template, not raw URL parameters.\nRequest-bound loggers retain completion attribution, while generic background\ncontinuations stop inheriting caller identity after the response completes.\nCapture covers the owning server process after initialization, not arbitrary\nconsole output, other worker processes, or host/container logs. Run one server\ninstance per process and database, as required by the single-tenant deployment\nmodel; this is not a cross-tenant or distributed log collector.\n\nFor CLI use, settings reads are remote. Google setup and telemetry retain their\nlocal defaults: pass `--target server` explicitly to configure the connected\nserver. `schedule list <project>` lists all schedule kinds, and\n`notify events --target server` discovers the server's event catalog.\n\nMCP returns legacy text JSON plus structured results. Objects keep their shape;\narrays use `{items: [...]}` in `structuredContent`, and scalars use `{value: ...}`.\nErrors preserve the existing envelope and CLI exit codes: HTTP 4xx (including\n429 policy limits) use exit 1; HTTP 5xx use exit 2. Server-provided `Retry-After`\nand request IDs are exposed as `retryAfterMs` and `requestId` when available;\nclients do not infer retryability from HTTP 429 or retry automatically.\nFor a write with an ambiguous outcome, inspect saved state or its receipt before\nretrying; a retry hint is not proof that repeating a write is safe.\n\n### Action boundaries\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
403
+ "markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `operations`, `prospecting`, `measurement`, `integrations`,\n`reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nAnalysis routes also return `playbooks`: Canonry's analyst playbooks for that\nwork, the same files its built-in agent reads. Read each one before\ninterpreting results. `canonry_help({ playbook: \"<slug>\" })` returns its full\ntext, a note on using it over MCP, and every available slug. Playbooks are\nguidance, not permission.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Setup:** Page Health needs no answer-engine provider; AI Visibility does.\nAfter a Page Health result on an install with no provider (a `NO_PROVIDER`\nnotice, or doctor's `providers.none-configured`), propose AI Visibility setup\nas the next step. The operator adds the provider key in the dashboard or in\ntheir own terminal; never ask for it in chat.\nRerunning `canonry bootstrap` after a provider change reloads saved provider\nsettings on a matching running local server and reports whether they became\nactive. If the server is offline, start it to apply the saved settings. For an\nexplicit reload of the connected server's own config, use\n`canonry settings reload-providers` or `canonry_providers_reload` with install\nadministrator authority. Remote servers are never reloaded automatically by\nbootstrap, and a local server that belongs to another install is left alone.\nPorts and database settings still need a restart.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Site Health:** read `canonry_site_health_issues` for stored technical findings,\naffected-page counts and example URLs, then `canonry_site_health_issue_pages`\nfor a selected issue's remaining pages. Pin subsequent reads to the returned\nrun. Inspect coverage and omissions: a passing score can still have findings,\nan older scan may lack cross-page evidence, and a partial scan cannot establish\nsite-wide absence. Advisory findings require judgment before proposing a repair.\nAudit evidence informs technical repairs and existing-page recommendations;\nit does not itself establish a new-blog opportunity or authorize any edit.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Compact `nextCursor` completes only `pageList`; use `list` to enumerate\none ranking, markets, observed names or cited domains, preserving filters.\nFirst-page sibling lists are bounded summaries. Keep sample sizes and ties\nvisible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\n### Agent operations\n\nUse `canonry_key_self` (CLI `canonry key whoami --format json`) to inspect the\ncurrent credential's scopes, project boundary, and host-derived `operator`\nauthority without exposing its token. Missing `operator` means unapproved.\n`canonry_settings_get` and\n`canonry_telemetry_get` describe the connected server, not the agent's local\nmachine. Telemetry reports configured preference, effective state, and any\nenvironment override; inspecting status never creates an anonymous identifier.\nAfter approval, `canonry_telemetry_update` changes that preference and\n`canonry_provider_settings_update` changes an already-configured provider's\nmodel/quota. Both require `settings.write`; neither accepts credentials.\nServer telemetry reads and updates additionally require operator authority.\nOrdinary audit-history reads omit internal telemetry events and their state.\n\nOperator authority is deny-by-default and separate from customer admin roles.\nThe deployment owner must approve a dedicated, instance-wide API key's ID in\nthe server environment variable `CANONRY_OPERATOR_KEY_IDS` (comma-separated IDs),\nthen restart the server. Empty/unset approves nobody; wildcards are invalid.\nKeep the bearer private to internal operators; never approve a customer-held or\nshared proxy/bootstrap key. Use `logs.read` for read-only diagnostics, adding\n`settings.write` only when telemetry control is required. Ordinary key creation,\naccount roles, OAuth consent, and caller headers cannot grant operator status.\nRevoking an approved key invalidates it immediately. Host enrollment is a trust\nbootstrap step, intentionally unavailable through customer-facing APIs.\nAPI, CLI, and MCP enforce the same boundary; MCP hides internal tools unless\nthe server confirms operator authority, including in explicit read-only mode.\nProject analytics, research, and normal project permissions are unchanged.\n\n`canonry_logs_list` reads bounded, redacted runtime events from both the\napplication logger and Fastify request/error logging. It requires an\ninstance-wide `logs.read` grant (or wildcard) and a host-approved direct bearer.\nBrowser sessions, OAuth/delegated credentials, customer admins, and project-scoped\nkeys cannot use it, even with a project filter or a matching allowlist ID.\nA `logs.read`-only key is read-only automatically, without a\nsecond `read` marker. Named `*.read` scopes cannot grant mutations; an explicit\nwrite grant is needed and remains subject to its route gates. Returned messages\nare sanitized and bounded; raw request or response bodies, headers, cookies,\nprovider payloads, and stacks are not\npart of the queryable surface. The same secret-redaction policy runs before\nconsole output and storage. Do not deliberately log secrets: redaction is a\ndefense in depth, not permission to put credentials into diagnostic strings.\nOpaque escaped payloads containing secret assignments are omitted when safe\npartial masking cannot be guaranteed; correlate their retained error codes and IDs.\n\nFile-backed hosts retain runtime logs in SQLite across restarts, bounded to\n10,000 events and seven days. In-memory hosts report `retention: \"process\"`.\nFilter by `actor`, `requestId`, `runId`, `projectId`, `module`, `level`, or an\ninclusive `since`/`until` interval. Keep filters unchanged when resuming an\nopaque cursor; retention eviction can invalidate it. Inspect `retentionPolicy`,\n`captureErrors`, `dropped`, `truncated`, and `retention` before drawing\nconclusions. Missing logs are not proof that an action did not happen. Use\n`canonry_project_history` or `canonry_history_global` for persistent audit events;\noffset pages have deterministic ordering but are not snapshots of concurrent writes.\n\nAudit `actor` comes from authenticated identity (`user:<id>` or `api-key:<id>`),\nnot a caller-supplied header. A delegated MCP credential records its originating\nuser as actor and the actual credential in `credentialId`. `requestId` correlates\nHTTP events; `userAgent` and `actorSession` are bounded, untrusted client hints,\nnever identity or permission grants. Older audit rows are not backfilled with\nidentities the server cannot prove.\n\nBoth shipped HTTP hosts issue restart-safe UUID request IDs and return them in\n`x-request-id`. Use that value to correlate a CLI/API failure with log entries;\nHTTP diagnostics retain the method and route template, not raw URL parameters.\nRequest-bound loggers retain completion attribution, while generic background\ncontinuations stop inheriting caller identity after the response completes.\nCapture covers the owning server process after initialization, not arbitrary\nconsole output, other worker processes, or host/container logs. Run one server\ninstance per process and database, as required by the single-tenant deployment\nmodel; this is not a cross-tenant or distributed log collector.\n\nFor CLI use, settings reads are remote. Google setup and telemetry retain their\nlocal defaults: pass `--target server` explicitly to configure the connected\nserver. `schedule list <project>` lists all schedule kinds, and\n`notify events --target server` discovers the server's event catalog.\n\nMCP returns legacy text JSON plus structured results. Objects keep their shape;\narrays use `{items: [...]}` in `structuredContent`, and scalars use `{value: ...}`.\nErrors preserve the existing envelope and CLI exit codes: HTTP 4xx (including\n429 policy limits) use exit 1; HTTP 5xx use exit 2. Server-provided `Retry-After`\nand request IDs are exposed as `retryAfterMs` and `requestId` when available;\nclients do not infer retryability from HTTP 429 or retry automatically.\nFor a write with an ambiguous outcome, inspect saved state or its receipt before\nretrying; a retry hint is not proof that repeating a write is safe.\n\n### Action boundaries\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
380
404
  };
381
405
 
382
406
  // src/mcp/operations-guide.ts
383
- function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
407
+ function operationsHelp(catalog, mode, intent = "", includeCatalog = false, playbooks = []) {
384
408
  const workflows = Object.keys(OPERATIONS_GUIDE.workflows);
385
409
  const words = new Set(intent.toLowerCase().split(/[^a-z0-9-]+/));
386
410
  const workflow = workflows.find((name) => OPERATIONS_GUIDE.workflows[name].keywords.some((word) => words.has(word))) ?? "status";
@@ -388,8 +412,10 @@ function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
388
412
  const available = /* @__PURE__ */ new Set([...catalog.coreTools, ...catalog.toolkits.filter((t) => t.loaded).flatMap((t) => t.tools)]);
389
413
  const reads = route.next;
390
414
  const requestedActions = "actions" in route ? route.actions : [];
415
+ const routePlaybooks = "playbooks" in route ? route.playbooks : [];
391
416
  const next = reads.filter((name) => available.has(name)).slice(0, 4);
392
417
  const actions = requestedActions.filter((name) => available.has(name));
418
+ const listedPlaybooks = routePlaybooks.filter((slug) => playbooks.includes(slug));
393
419
  if (reads.includes("canonry_projects_list") && next.length < 2 && available.has("canonry_project_overview") && !next.includes("canonry_project_overview")) {
394
420
  next.push("canonry_project_overview");
395
421
  }
@@ -406,6 +432,7 @@ function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
406
432
  ...actions.length ? { actions } : {},
407
433
  workflows,
408
434
  guidance: route.guidance,
435
+ ...listedPlaybooks.length ? { playbooks: listedPlaybooks, playbookRule: OPERATIONS_GUIDE.playbookRule } : {},
409
436
  approvalBoundary: OPERATIONS_GUIDE.approvalBoundary,
410
437
  approvalRule: OPERATIONS_GUIDE.approvalRule,
411
438
  authority: OPERATIONS_GUIDE.authority,
@@ -416,6 +443,45 @@ function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
416
443
  };
417
444
  }
418
445
 
446
+ // src/mcp/playbooks.ts
447
+ import fs from "fs";
448
+ import path from "path";
449
+ var PLAYBOOK_SLUG = /^[a-z0-9-]{1,64}$/;
450
+ var SKILL_SLUG = "aero";
451
+ var GUIDE_SLUG = "agent-operations";
452
+ function availablePlaybooks() {
453
+ const dir = aeroSkillDir();
454
+ if (!dir) return [];
455
+ const references = path.join(dir, "references");
456
+ const slugs = fs.existsSync(references) ? fs.readdirSync(references).filter((file) => file.endsWith(".md")).map((file) => file.slice(0, -".md".length)).filter((slug) => PLAYBOOK_SLUG.test(slug) && slug !== SKILL_SLUG).sort() : [];
457
+ return [SKILL_SLUG, ...slugs];
458
+ }
459
+ function readPlaybook(slug) {
460
+ const playbooks = availablePlaybooks();
461
+ const dir = aeroSkillDir();
462
+ if (!dir || !playbooks.includes(slug)) {
463
+ throw new CliError({
464
+ code: "NOT_FOUND",
465
+ message: `No playbook "${slug}". Use a slug from availablePlaybooks.`,
466
+ details: { availablePlaybooks: playbooks }
467
+ });
468
+ }
469
+ const file = slug === SKILL_SLUG ? "SKILL.md" : path.join("references", `${slug}.md`);
470
+ const content = slug === GUIDE_SLUG ? OPERATIONS_GUIDE.markdown : fs.readFileSync(path.join(dir, file), "utf8");
471
+ return `Playbook: ${slug}
472
+ Note: ${OPERATIONS_GUIDE.playbookNote}
473
+ Available: ${playbooks.join(", ")}
474
+
475
+ ${content}`;
476
+ }
477
+ function aeroSkillDir() {
478
+ try {
479
+ return resolveAeroSkillDir();
480
+ } catch {
481
+ return null;
482
+ }
483
+ }
484
+
419
485
  // src/mcp/server.ts
420
486
  function createCanonryMcpServer(options = {}) {
421
487
  return createCanonryMcpServerWithCatalog(options).server;
@@ -496,23 +562,27 @@ var loadToolkitInputSchema = z.object({
496
562
  });
497
563
  var helpInputSchema = z.object({
498
564
  intent: z.string().max(200).optional().describe("Workflow (status, diagnose, prospecting, measurement, integrations, reports) or a short task description."),
499
- includeCatalog: z.boolean().optional().describe("Include full toolkit details. Omit for a compact, actionable route.")
565
+ includeCatalog: z.boolean().optional().describe("Include full toolkit details. Omit for a compact, actionable route."),
566
+ playbook: z.string().regex(PLAYBOOK_SLUG).optional().describe('Slug from a help result\'s `playbooks`, such as "regression-playbook". Returns that analyst playbook in full instead of a route.')
500
567
  });
501
568
  function registerMetaTools(server, catalog, opts) {
502
569
  server.registerTool(
503
570
  "canonry_help",
504
571
  {
505
572
  title: "Guide a Canonry workflow",
506
- description: "Start here: route an intent to available stored-evidence tools, separately listed actions requiring approval, and workflow guidance. No provider calls or installation required. Optionally include full toolkit details.",
573
+ description: "Start here: route an intent to available stored-evidence tools, separately listed actions requiring approval, workflow guidance, and the analyst playbooks to read. Pass `playbook` to read one in full. No provider calls or installation required. Optionally include full toolkit details.",
507
574
  inputSchema: helpInputSchema,
508
575
  annotations: { readOnlyHint: true, idempotentHint: true, destructiveHint: false, openWorldHint: false }
509
576
  },
510
577
  async (input) => {
511
578
  try {
512
579
  const parsed = helpInputSchema.parse(input ?? {});
580
+ if (parsed.playbook !== void 0) {
581
+ return { content: [{ type: "text", text: readPlaybook(parsed.playbook) }] };
582
+ }
513
583
  const update = readUpdateAvailable(opts.updateAvailable);
514
584
  const result = {
515
- ...operationsHelp(catalog.helpResult(), opts.mode, parsed.intent, parsed.includeCatalog),
585
+ ...operationsHelp(catalog.helpResult(), opts.mode, parsed.intent, parsed.includeCatalog, availablePlaybooks()),
516
586
  ...update ? { updateAvailable: updateNoticePayload(update) } : {}
517
587
  };
518
588
  return { ...jsonToolResult(result), structuredContent: result };
@@ -28,7 +28,7 @@ async function buildSetupState() {
28
28
  }
29
29
  if (dbPath && fs.existsSync(dbPath)) {
30
30
  try {
31
- const { createClient, projects, queries: queriesTable } = await import("./src-AQ5MHQGQ.js");
31
+ const { createClient, projects, queries: queriesTable } = await import("./src-QC2VNJWJ.js");
32
32
  const db = createClient(dbPath);
33
33
  project_count = db.select({ id: projects.id }).from(projects).all().length;
34
34
  const firstQuery = db.select({ id: queriesTable.id }).from(queriesTable).limit(1).all();
@@ -47,7 +47,7 @@ function queueServeHandoff() {
47
47
  async function runPendingServeHandoff(format) {
48
48
  if (!pendingServeHandoff) return;
49
49
  pendingServeHandoff = false;
50
- const { serveCommand } = await import("./serve-7HN3VT6J.js");
50
+ const { serveCommand } = await import("./serve-VU3E7XTX.js");
51
51
  await serveCommand(format);
52
52
  }
53
53
 
@@ -17,7 +17,7 @@ import {
17
17
  mergeGscQueryTotalsWithFallback,
18
18
  readGscQueryDailyRows,
19
19
  readLatestGscDataDate
20
- } from "./chunk-PRCBHOVR.js";
20
+ } from "./chunk-KUMHO22S.js";
21
21
  import {
22
22
  competitors,
23
23
  gbpDailyMetrics,
@@ -35,7 +35,7 @@ import {
35
35
  queries,
36
36
  querySnapshots,
37
37
  runs
38
- } from "./chunk-PH4AESRE.js";
38
+ } from "./chunk-HRFPGXON.js";
39
39
  import {
40
40
  CitationStates,
41
41
  RunKinds,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  REGISTERED_CLI_COMMANDS
3
- } from "./chunk-KHIZSTDP.js";
3
+ } from "./chunk-DEQC5XVD.js";
4
4
  import "./chunk-6GO5VVAC.js";
5
5
  import "./chunk-2EWZ3DJ4.js";
6
6
  import "./chunk-VJWDBFSL.js";
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node --import tsx
2
2
  import {
3
3
  REGISTERED_CLI_COMMANDS
4
- } from "./chunk-KHIZSTDP.js";
4
+ } from "./chunk-DEQC5XVD.js";
5
5
  import {
6
6
  buildSetupState,
7
7
  runPendingServeHandoff
8
- } from "./chunk-LOMRNRML.js";
8
+ } from "./chunk-SWWZ733W.js";
9
9
  import "./chunk-6GO5VVAC.js";
10
10
  import "./chunk-2EWZ3DJ4.js";
11
11
  import "./chunk-VJWDBFSL.js";
@@ -7,12 +7,12 @@ import {
7
7
  } from "./chunk-HGMYEDAQ.js";
8
8
  import {
9
9
  anyUsersExist
10
- } from "./chunk-PRCBHOVR.js";
10
+ } from "./chunk-KUMHO22S.js";
11
11
  import "./chunk-O4WBYEGV.js";
12
12
  import "./chunk-3MGM3U6V.js";
13
13
  import {
14
14
  createClient
15
- } from "./chunk-PH4AESRE.js";
15
+ } from "./chunk-HRFPGXON.js";
16
16
  import "./chunk-PM2DB3HE.js";
17
17
  import "./chunk-MLKGABMK.js";
18
18
 
@@ -40,7 +40,7 @@ function parseDemoTrustedProxies(values) {
40
40
  async function demoCommand(options) {
41
41
  const { host, port } = parseDemoListenOptions(options);
42
42
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
43
- const { createDemoServer } = await import("./demo-server-ISJOEJN5.js");
43
+ const { createDemoServer } = await import("./demo-server-MRGL3SNP.js");
44
44
  const app = await createDemoServer({ trustProxy });
45
45
  let stopping = false;
46
46
  const stop = () => {
@@ -5,7 +5,7 @@ import {
5
5
  computeFactorAverages,
6
6
  layoutSiteCrawlGraphInput,
7
7
  persistSiteCrawlGraphLayout
8
- } from "./chunk-LBNUTWPK.js";
8
+ } from "./chunk-OIRHCT63.js";
9
9
  import {
10
10
  canonryMcpTools
11
11
  } from "./chunk-MUYTDD35.js";
@@ -18,7 +18,7 @@ import "./chunk-HGMYEDAQ.js";
18
18
  import {
19
19
  HISTORY_WINDOW_RUNS,
20
20
  IntelligenceService
21
- } from "./chunk-BTMLE3EN.js";
21
+ } from "./chunk-ZMMS3FAR.js";
22
22
  import "./chunk-TZRYVW75.js";
23
23
  import {
24
24
  determineCitationState
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  apiRoutes,
28
28
  assessConversionTrackingIntegrity
29
- } from "./chunk-PRCBHOVR.js";
29
+ } from "./chunk-KUMHO22S.js";
30
30
  import "./chunk-O4WBYEGV.js";
31
31
  import "./chunk-3MGM3U6V.js";
32
32
  import {
@@ -104,7 +104,7 @@ import {
104
104
  siteCrawlPages,
105
105
  siteCrawlSnapshots,
106
106
  trafficSources
107
- } from "./chunk-PH4AESRE.js";
107
+ } from "./chunk-HRFPGXON.js";
108
108
  import {
109
109
  AI_ENGINE_DOMAINS,
110
110
  GA_OVERVIEW_HISTORY_DAYS,