@ainyc/canonry 4.110.0 → 4.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +1 -1
  2. package/assets/assets/{BacklinksPage-Duk8YbV2.js → BacklinksPage-0OUPoMJf.js} +1 -1
  3. package/assets/assets/ChartPrimitives-BeJemaLi.js +1 -0
  4. package/assets/assets/ProjectPage-CD0RS8DR.js +7 -0
  5. package/assets/assets/{RunRow-DH8UMAwj.js → RunRow-CCnuv5wi.js} +1 -1
  6. package/assets/assets/{RunsPage-OPteH1b_.js → RunsPage-IqTj8i9c.js} +1 -1
  7. package/assets/assets/{SettingsPage-7cspMOFv.js → SettingsPage-DKdvVPVp.js} +1 -1
  8. package/assets/assets/{TrafficPage-D4pcnfc8.js → TrafficPage-xPENJ4Du.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-D-KbCCEK.js → TrafficSourceDetailPage-CP6o754T.js} +1 -1
  10. package/assets/assets/{arrow-left-M8KVuve8.js → arrow-left-DGiw6bsJ.js} +1 -1
  11. package/assets/assets/{extract-error-message-D2aTaSV5.js → extract-error-message-CYh3RHSN.js} +1 -1
  12. package/assets/assets/{index-ChPgQUZ5.js → index-BpHZkgFH.js} +51 -51
  13. package/assets/assets/index-CD6LKwQu.css +1 -0
  14. package/assets/assets/{trash-2-BNVgf5NY.js → trash-2-DBeJW7Iw.js} +1 -1
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-X4LLTNQZ.js → chunk-6M2ALGJA.js} +1 -1
  17. package/dist/{chunk-6PHBWPPN.js → chunk-KS2M7B5E.js} +8 -4
  18. package/dist/{chunk-JGRVQJHX.js → chunk-UOMNYP5T.js} +61 -6
  19. package/dist/{chunk-YQ4KOC5Z.js → chunk-VICGMHY2.js} +4 -0
  20. package/dist/cli.js +400 -102
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-BGLF7DQW.js → intelligence-service-RGOY43QR.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +10 -10
  25. package/assets/assets/ChartPrimitives-aLxtVH28.js +0 -1
  26. package/assets/assets/ProjectPage-Bqd0JvpC.js +0 -7
  27. package/assets/assets/index-CjrSrPKf.css +0 -1
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setTelemetrySource,
30
30
  showFirstRunNotice,
31
31
  trackEvent
32
- } from "./chunk-6PHBWPPN.js";
32
+ } from "./chunk-KS2M7B5E.js";
33
33
  import {
34
34
  CliError,
35
35
  EXIT_SYSTEM_ERROR,
@@ -46,7 +46,7 @@ import {
46
46
  saveConfig,
47
47
  saveConfigPatch,
48
48
  usageError
49
- } from "./chunk-X4LLTNQZ.js";
49
+ } from "./chunk-6M2ALGJA.js";
50
50
  import {
51
51
  apiKeys,
52
52
  createClient,
@@ -54,7 +54,7 @@ import {
54
54
  projects,
55
55
  queries,
56
56
  renderReportHtml
57
- } from "./chunk-JGRVQJHX.js";
57
+ } from "./chunk-UOMNYP5T.js";
58
58
  import {
59
59
  BacklinkSources,
60
60
  CcReleaseSyncStatuses,
@@ -80,7 +80,7 @@ import {
80
80
  providerQuotaPolicySchema,
81
81
  resolveProviderInput,
82
82
  winnabilityClassSchema
83
- } from "./chunk-YQ4KOC5Z.js";
83
+ } from "./chunk-VICGMHY2.js";
84
84
 
85
85
  // src/cli.ts
86
86
  import { pathToFileURL } from "url";
@@ -126,9 +126,9 @@ import { parseArgs } from "util";
126
126
  function commandId(spec) {
127
127
  return spec.path.join(".");
128
128
  }
129
- function matchesPath(args, path9) {
130
- if (args.length < path9.length) return false;
131
- return path9.every((segment, index) => args[index] === segment);
129
+ function matchesPath(args, path10) {
130
+ if (args.length < path10.length) return false;
131
+ return path10.every((segment, index) => args[index] === segment);
132
132
  }
133
133
  function withGlobalOptions(options) {
134
134
  const base = options ? { ...options } : {};
@@ -1973,6 +1973,272 @@ async function pollSession(client, project, sessionId, quiet = false) {
1973
1973
  }
1974
1974
  }
1975
1975
 
1976
+ // src/commands/discover-eval.ts
1977
+ import fs2 from "fs";
1978
+ import path from "path";
1979
+
1980
+ // src/discovery-eval.ts
1981
+ var DISCOVERY_EVAL_PANEL = [
1982
+ {
1983
+ slug: "eval-local-single-intent",
1984
+ displayName: "Summit Roof Coatings",
1985
+ domain: "summitroofcoatings.com",
1986
+ icp: "commercial roof coating contractor in Phoenix, Arizona",
1987
+ buyer: "commercial property managers responsible for flat-roof maintenance budgets",
1988
+ locations: [{ label: "phoenix", city: "Phoenix", region: "Arizona", country: "US" }]
1989
+ },
1990
+ {
1991
+ slug: "eval-local-multi-intent",
1992
+ displayName: "Peak Comfort HVAC",
1993
+ domain: "peakcomforthvac.com",
1994
+ icp: "residential HVAC installation, repair, and maintenance company in Denver, Colorado",
1995
+ buyer: "homeowners with aging furnaces or AC units comparing replacement and repair options",
1996
+ locations: [{ label: "denver", city: "Denver", region: "Colorado", country: "US" }]
1997
+ },
1998
+ {
1999
+ slug: "eval-b2b-saas",
2000
+ displayName: "QuoteBeam",
2001
+ domain: "quotebeam.io",
2002
+ icp: "quoting and proposal software for residential solar installers",
2003
+ buyer: "solar sales managers evaluating quoting tools for a 10-50 rep team",
2004
+ locations: []
2005
+ },
2006
+ {
2007
+ slug: "eval-national-ecommerce",
2008
+ displayName: "Willow and Sprout",
2009
+ domain: "willowandsprout.com",
2010
+ icp: "organic cotton baby clothing brand sold online across the US",
2011
+ buyer: "expecting parents researching non-toxic baby essentials",
2012
+ locations: []
2013
+ },
2014
+ {
2015
+ slug: "eval-problem-heavy-consumer",
2016
+ displayName: "SwiftRemit",
2017
+ domain: "swiftremit.app",
2018
+ icp: "mobile app for sending money internationally with low fees",
2019
+ buyer: "immigrants who send money home to family every month",
2020
+ locations: []
2021
+ }
2022
+ ];
2023
+ var EVAL_CANONICAL_FLOOR = 8;
2024
+ var EVAL_BANDS = {
2025
+ /** canonicalCount must be >= baseline * this factor (and >= the floor). */
2026
+ canonicalCountFactor: 0.6,
2027
+ /** retention may drop at most this many absolute points below baseline. */
2028
+ retentionDrop: 0.2,
2029
+ /** brandShare may exceed baseline by at most this (and never exceed 0.1). */
2030
+ brandShareSlack: 0.05,
2031
+ brandShareCeiling: 0.1,
2032
+ /** duration must be <= baseline * factor + slack seconds. */
2033
+ durationFactor: 2,
2034
+ durationSlackSeconds: 30
2035
+ };
2036
+ function scoreSession(shape, session) {
2037
+ const raw = session.seedCountRaw ?? 0;
2038
+ const brandFiltered = session.seedBrandFilteredCount ?? 0;
2039
+ const preFilterTotal = raw + brandFiltered;
2040
+ const truncated = session.canonicalCount == null;
2041
+ const canonicalCount = session.canonicalCount ?? session.seedCount ?? 0;
2042
+ const started = session.startedAt ? Date.parse(session.startedAt) : NaN;
2043
+ const finished = session.finishedAt ? Date.parse(session.finishedAt) : NaN;
2044
+ return {
2045
+ shape,
2046
+ seedCountRaw: raw,
2047
+ canonicalCount,
2048
+ canonicalCountTruncated: truncated,
2049
+ retention: raw > 0 ? canonicalCount / raw : 0,
2050
+ brandShare: preFilterTotal > 0 ? brandFiltered / preFilterTotal : 0,
2051
+ groundingShare: raw > 0 ? (session.seedFromGroundingCount ?? 0) / raw : 0,
2052
+ bandPairFraction: session.dedupBandPairFraction ?? null,
2053
+ probeCount: session.probeCount ?? 0,
2054
+ warning: session.warning ?? null,
2055
+ durationSeconds: Number.isFinite(started) && Number.isFinite(finished) ? Math.round((finished - started) / 1e3) : null
2056
+ };
2057
+ }
2058
+ function compareToBaseline(scorecards, baseline) {
2059
+ const regressions = [];
2060
+ const notes = [];
2061
+ const bySlug = new Map(scorecards.map((c) => [c.shape, c]));
2062
+ for (const base of baseline.scorecards) {
2063
+ const current = bySlug.get(base.shape);
2064
+ if (!current) {
2065
+ regressions.push(`${base.shape}: missing from this run (baseline shape not evaluated)`);
2066
+ continue;
2067
+ }
2068
+ bySlug.delete(base.shape);
2069
+ if (current.canonicalCount < EVAL_CANONICAL_FLOOR) {
2070
+ regressions.push(
2071
+ `${base.shape}: canonicalCount ${current.canonicalCount} is below the absolute platform floor (${EVAL_CANONICAL_FLOOR})`
2072
+ );
2073
+ }
2074
+ if (current.canonicalCount < base.canonicalCount * EVAL_BANDS.canonicalCountFactor) {
2075
+ regressions.push(
2076
+ `${base.shape}: canonicalCount ${current.canonicalCount} vs baseline ${base.canonicalCount} (band: >= ${EVAL_BANDS.canonicalCountFactor}x)`
2077
+ );
2078
+ }
2079
+ if (current.canonicalCount < base.canonicalCount && current.retention < base.retention - EVAL_BANDS.retentionDrop) {
2080
+ regressions.push(
2081
+ `${base.shape}: retention ${current.retention.toFixed(2)} vs baseline ${base.retention.toFixed(2)} (band: -${EVAL_BANDS.retentionDrop}), with canonicals also down (${current.canonicalCount} < ${base.canonicalCount})`
2082
+ );
2083
+ }
2084
+ const brandCeiling = Math.min(base.brandShare + EVAL_BANDS.brandShareSlack, EVAL_BANDS.brandShareCeiling);
2085
+ if (current.brandShare > brandCeiling) {
2086
+ regressions.push(
2087
+ `${base.shape}: brandShare ${current.brandShare.toFixed(2)} exceeds ${brandCeiling.toFixed(2)} (no-brand rule regressed)`
2088
+ );
2089
+ }
2090
+ if (current.warning) {
2091
+ regressions.push(`${base.shape}: collapse warning fired: ${current.warning.slice(0, 80)}`);
2092
+ }
2093
+ if (current.durationSeconds != null && base.durationSeconds != null && current.durationSeconds > base.durationSeconds * EVAL_BANDS.durationFactor + EVAL_BANDS.durationSlackSeconds) {
2094
+ regressions.push(
2095
+ `${base.shape}: duration ${current.durationSeconds}s vs baseline ${base.durationSeconds}s (band: ${EVAL_BANDS.durationFactor}x + ${EVAL_BANDS.durationSlackSeconds}s)`
2096
+ );
2097
+ }
2098
+ if (current.canonicalCountTruncated) {
2099
+ notes.push(`${base.shape}: engine predates canonical_count; using truncated seedCount (understates quality)`);
2100
+ }
2101
+ }
2102
+ for (const [slug] of bySlug) {
2103
+ notes.push(`${slug}: new shape with no baseline entry (add it via --update-baseline)`);
2104
+ }
2105
+ return { pass: regressions.length === 0, regressions, notes };
2106
+ }
2107
+
2108
+ // src/commands/discover-eval.ts
2109
+ var DEFAULT_BASELINE_PATH = "canonry-discovery-eval-baseline.json";
2110
+ var POLL_INTERVAL_MS2 = 5e3;
2111
+ var SHAPE_TIMEOUT_MS = 10 * 6e4;
2112
+ async function runDiscoveryEvalPanel(client, shapes, opts) {
2113
+ const scorecards = [];
2114
+ const pollInterval = opts.pollIntervalMs ?? POLL_INTERVAL_MS2;
2115
+ const timeout = opts.shapeTimeoutMs ?? SHAPE_TIMEOUT_MS;
2116
+ const now = opts.now ?? Date.now;
2117
+ for (const shape of shapes) {
2118
+ await client.putProject(shape.slug, {
2119
+ displayName: shape.displayName,
2120
+ canonicalDomain: shape.domain,
2121
+ country: "US",
2122
+ language: "en",
2123
+ ...shape.locations.length > 0 ? { locations: shape.locations, defaultLocation: shape.locations[0].label } : {}
2124
+ });
2125
+ const started = await client.triggerDiscoveryRun(shape.slug, {
2126
+ icpDescription: shape.icp,
2127
+ buyerDescription: shape.buyer,
2128
+ maxProbes: opts.maxProbes ?? 2,
2129
+ probeConcurrency: opts.probeConcurrency ?? 2,
2130
+ ...opts.seedProviders && opts.seedProviders.length > 0 ? { seedProviders: opts.seedProviders } : {}
2131
+ });
2132
+ const sessionId = typeof started.sessionId === "string" ? started.sessionId : "";
2133
+ if (!sessionId) {
2134
+ throw new CliError({
2135
+ code: "EVAL_SESSION_START_FAILED",
2136
+ message: `${shape.slug}: discover run returned no sessionId`,
2137
+ exitCode: EXIT_USER_ERROR
2138
+ });
2139
+ }
2140
+ const deadline = now() + timeout;
2141
+ let session;
2142
+ for (; ; ) {
2143
+ const rows = await client.listDiscoverySessions(shape.slug, { limit: 10 });
2144
+ session = rows.find((r) => r.id === sessionId);
2145
+ if (session?.status === "completed") break;
2146
+ if (session?.status === "failed") {
2147
+ throw new CliError({
2148
+ code: "EVAL_SESSION_FAILED",
2149
+ message: `${shape.slug}: discovery session failed`,
2150
+ exitCode: EXIT_USER_ERROR,
2151
+ details: { sessionId }
2152
+ });
2153
+ }
2154
+ if (now() > deadline) {
2155
+ throw new CliError({
2156
+ code: "EVAL_SESSION_TIMEOUT",
2157
+ message: `${shape.slug}: session did not complete within ${Math.round(timeout / 6e4)} minutes`,
2158
+ exitCode: EXIT_USER_ERROR,
2159
+ details: { sessionId }
2160
+ });
2161
+ }
2162
+ await new Promise((r) => setTimeout(r, pollInterval));
2163
+ }
2164
+ scorecards.push(scoreSession(shape.slug, session));
2165
+ }
2166
+ return scorecards;
2167
+ }
2168
+ function renderHuman(scorecards, verdict) {
2169
+ console.log("SHAPE RAW CANON RETENTION BRAND GROUND BAND TIME");
2170
+ for (const c of scorecards) {
2171
+ console.log(
2172
+ [
2173
+ c.shape.padEnd(30),
2174
+ String(c.seedCountRaw).padStart(4),
2175
+ String(c.canonicalCount).padStart(6) + (c.canonicalCountTruncated ? "*" : " "),
2176
+ c.retention.toFixed(2).padStart(9),
2177
+ c.brandShare.toFixed(2).padStart(6),
2178
+ c.groundingShare.toFixed(2).padStart(7),
2179
+ (c.bandPairFraction ?? 0).toFixed(2).padStart(5),
2180
+ c.durationSeconds == null ? " ?" : `${String(c.durationSeconds).padStart(4)}s`
2181
+ ].join(" ")
2182
+ );
2183
+ if (c.warning) console.log(` warning: ${c.warning}`);
2184
+ }
2185
+ if (verdict) {
2186
+ for (const note of verdict.notes) console.log(`note: ${note}`);
2187
+ for (const regression of verdict.regressions) console.log(`REGRESSION: ${regression}`);
2188
+ console.log(verdict.pass ? "PASS: no regressions against the baseline." : "FAIL: regressions detected.");
2189
+ } else {
2190
+ console.log("No baseline compared (wrote or missing baseline).");
2191
+ }
2192
+ }
2193
+ async function discoverEvalWithClient(client, opts) {
2194
+ const selected = opts.shapes && opts.shapes.length > 0 ? DISCOVERY_EVAL_PANEL.filter((s) => opts.shapes.includes(s.slug)) : DISCOVERY_EVAL_PANEL;
2195
+ if (selected.length === 0) {
2196
+ throw new CliError({
2197
+ code: "EVAL_NO_SHAPES",
2198
+ message: `no matching shapes; known: ${DISCOVERY_EVAL_PANEL.map((s) => s.slug).join(", ")}`,
2199
+ exitCode: EXIT_USER_ERROR
2200
+ });
2201
+ }
2202
+ const scorecards = await runDiscoveryEvalPanel(client, selected, opts);
2203
+ const baselinePath = path.resolve(opts.baseline ?? DEFAULT_BASELINE_PATH);
2204
+ if (opts.updateBaseline) {
2205
+ const baseline2 = { capturedAt: (/* @__PURE__ */ new Date()).toISOString(), scorecards };
2206
+ fs2.writeFileSync(baselinePath, JSON.stringify(baseline2, null, 2) + "\n");
2207
+ if (opts.format === "json" || opts.format === "jsonl") {
2208
+ console.log(JSON.stringify({ scorecards, baselineWritten: baselinePath }, null, 2));
2209
+ } else {
2210
+ renderHuman(scorecards, null);
2211
+ console.log(`Baseline written: ${baselinePath}`);
2212
+ }
2213
+ return;
2214
+ }
2215
+ if (!fs2.existsSync(baselinePath)) {
2216
+ throw new CliError({
2217
+ code: "EVAL_NO_BASELINE",
2218
+ message: `no baseline at ${baselinePath}; run with --update-baseline to capture one`,
2219
+ exitCode: EXIT_USER_ERROR
2220
+ });
2221
+ }
2222
+ const baseline = JSON.parse(fs2.readFileSync(baselinePath, "utf8"));
2223
+ const verdict = compareToBaseline(scorecards, baseline);
2224
+ if (opts.format === "json" || opts.format === "jsonl") {
2225
+ console.log(JSON.stringify({ scorecards, verdict, baseline: { capturedAt: baseline.capturedAt } }, null, 2));
2226
+ } else {
2227
+ renderHuman(scorecards, verdict);
2228
+ }
2229
+ if (!verdict.pass) {
2230
+ throw new CliError({
2231
+ code: "EVAL_REGRESSION",
2232
+ message: `${verdict.regressions.length} regression${verdict.regressions.length === 1 ? "" : "s"} against the baseline`,
2233
+ exitCode: EXIT_USER_ERROR,
2234
+ details: { regressions: verdict.regressions }
2235
+ });
2236
+ }
2237
+ }
2238
+ async function discoverEval(opts) {
2239
+ await discoverEvalWithClient(createApiClient(), opts);
2240
+ }
2241
+
1976
2242
  // src/cli-commands/discover.ts
1977
2243
  function parseFloatOption(values, key, usage) {
1978
2244
  const raw = values[key];
@@ -2096,6 +2362,38 @@ var DISCOVER_CLI_COMMANDS = [
2096
2362
  });
2097
2363
  }
2098
2364
  },
2365
+ {
2366
+ path: ["discover", "eval"],
2367
+ usage: "canonry discover eval [--baseline <path>] [--update-baseline] [--shape eval-b2b-saas ...] [--seed-provider gemini --seed-provider openai] [--max-probes 2] [--probe-concurrency 2] [--format json]",
2368
+ options: {
2369
+ baseline: stringOption(),
2370
+ "update-baseline": { type: "boolean", default: false },
2371
+ shape: multiStringOption(),
2372
+ "seed-provider": multiStringOption(),
2373
+ "max-probes": stringOption(),
2374
+ "probe-concurrency": stringOption()
2375
+ },
2376
+ run: async (input) => {
2377
+ const usage = "canonry discover eval [--baseline <path>] [--update-baseline] [--shape eval-b2b-saas ...] [--seed-provider gemini --seed-provider openai] [--max-probes 2] [--probe-concurrency 2] [--format json]";
2378
+ await discoverEval({
2379
+ baseline: getString(input.values, "baseline"),
2380
+ updateBaseline: getBoolean(input.values, "update-baseline"),
2381
+ shapes: getStringArray(input.values, "shape"),
2382
+ seedProviders: getStringArray(input.values, "seed-provider"),
2383
+ maxProbes: parseIntegerOption(input, "max-probes", {
2384
+ command: "discover.eval",
2385
+ usage,
2386
+ message: "--max-probes must be an integer"
2387
+ }),
2388
+ probeConcurrency: parseIntegerOption(input, "probe-concurrency", {
2389
+ command: "discover.eval",
2390
+ usage,
2391
+ message: "--probe-concurrency must be an integer"
2392
+ }),
2393
+ format: input.format
2394
+ });
2395
+ }
2396
+ },
2099
2397
  {
2100
2398
  path: ["discover", "seed"],
2101
2399
  usage: 'canonry discover seed <project> [--icp "..."] [--buyer "..."] [--seed-provider gemini --seed-provider openai] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--probe-concurrency 3] [--wait] [--format json]',
@@ -2650,9 +2948,9 @@ async function gaConnect(project, opts) {
2650
2948
  propertyId: opts.propertyId
2651
2949
  };
2652
2950
  if (opts.keyFile) {
2653
- const fs12 = await import("fs");
2951
+ const fs13 = await import("fs");
2654
2952
  try {
2655
- const content = fs12.readFileSync(opts.keyFile, "utf-8");
2953
+ const content = fs13.readFileSync(opts.keyFile, "utf-8");
2656
2954
  JSON.parse(content);
2657
2955
  body.keyJson = content;
2658
2956
  } catch (e) {
@@ -3860,9 +4158,9 @@ async function getCommand(opts) {
3860
4158
  console.log(JSON.stringify(leaf, null, 2));
3861
4159
  }
3862
4160
  }
3863
- function walkPath(value, path9) {
3864
- if (!path9 || path9 === ".") return value;
3865
- const segments = path9.split(".").flatMap((part) => {
4161
+ function walkPath(value, path10) {
4162
+ if (!path10 || path10 === ".") return value;
4163
+ const segments = path10.split(".").flatMap((part) => {
3866
4164
  const tokens = [];
3867
4165
  let i = 0;
3868
4166
  const bracketStart = part.indexOf("[");
@@ -3910,13 +4208,13 @@ var GET_CLI_COMMANDS = [
3910
4208
  },
3911
4209
  run: async (input) => {
3912
4210
  const project = requireProject(input, "get", USAGE2);
3913
- const path9 = requirePositional(input, 1, {
4211
+ const path10 = requirePositional(input, 1, {
3914
4212
  command: "get",
3915
4213
  usage: USAGE2,
3916
4214
  message: 'path is required (e.g. "scores.mentionShare.value")'
3917
4215
  });
3918
4216
  const from = getString(input.values, "from");
3919
- await getCommand({ project, path: path9, from, format: input.format });
4217
+ await getCommand({ project, path: path10, from, format: input.format });
3920
4218
  }
3921
4219
  }
3922
4220
  ];
@@ -3955,9 +4253,9 @@ async function trafficConnectWordpress(project, opts) {
3955
4253
  }
3956
4254
  let applicationPassword = opts.appPassword?.trim() ?? "";
3957
4255
  if (!applicationPassword && opts.appPasswordFile) {
3958
- const fs12 = await import("fs");
4256
+ const fs13 = await import("fs");
3959
4257
  try {
3960
- applicationPassword = fs12.readFileSync(opts.appPasswordFile, "utf-8").trim();
4258
+ applicationPassword = fs13.readFileSync(opts.appPasswordFile, "utf-8").trim();
3961
4259
  } catch (e) {
3962
4260
  const msg = e instanceof Error ? e.message : String(e);
3963
4261
  throw new CliError({
@@ -4013,10 +4311,10 @@ async function trafficConnectCloudRun(project, opts) {
4013
4311
  details: { project }
4014
4312
  });
4015
4313
  }
4016
- const fs12 = await import("fs");
4314
+ const fs13 = await import("fs");
4017
4315
  let keyJson;
4018
4316
  try {
4019
- keyJson = fs12.readFileSync(opts.serviceAccountKey, "utf-8");
4317
+ keyJson = fs13.readFileSync(opts.serviceAccountKey, "utf-8");
4020
4318
  JSON.parse(keyJson);
4021
4319
  } catch (e) {
4022
4320
  const msg = e instanceof Error ? e.message : String(e);
@@ -4076,9 +4374,9 @@ async function trafficConnectVercel(project, opts) {
4076
4374
  }
4077
4375
  let token = opts.token?.trim() ?? "";
4078
4376
  if (!token && opts.tokenFile) {
4079
- const fs12 = await import("fs");
4377
+ const fs13 = await import("fs");
4080
4378
  try {
4081
- token = fs12.readFileSync(opts.tokenFile, "utf-8").trim();
4379
+ token = fs13.readFileSync(opts.tokenFile, "utf-8").trim();
4082
4380
  } catch (e) {
4083
4381
  const msg = e instanceof Error ? e.message : String(e);
4084
4382
  throw new CliError({
@@ -5892,7 +6190,7 @@ var KEYS_CLI_COMMANDS = [
5892
6190
  ];
5893
6191
 
5894
6192
  // src/commands/keyword.ts
5895
- import fs2 from "fs";
6193
+ import fs3 from "fs";
5896
6194
  function getClient12() {
5897
6195
  return createApiClient();
5898
6196
  }
@@ -5960,7 +6258,7 @@ async function listKeywords(project, format) {
5960
6258
  }
5961
6259
  }
5962
6260
  async function importKeywords(project, filePath, format) {
5963
- if (!fs2.existsSync(filePath)) {
6261
+ if (!fs3.existsSync(filePath)) {
5964
6262
  throw new CliError({
5965
6263
  code: "KEYWORD_IMPORT_FILE_NOT_FOUND",
5966
6264
  message: `File not found: ${filePath}`,
@@ -5971,7 +6269,7 @@ async function importKeywords(project, filePath, format) {
5971
6269
  }
5972
6270
  });
5973
6271
  }
5974
- const content = fs2.readFileSync(filePath, "utf-8");
6272
+ const content = fs3.readFileSync(filePath, "utf-8");
5975
6273
  const keywords = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
5976
6274
  if (keywords.length === 0) {
5977
6275
  if (isMachineFormat(format)) {
@@ -6172,7 +6470,7 @@ var KEYWORD_CLI_COMMANDS = [
6172
6470
  ];
6173
6471
 
6174
6472
  // src/commands/query.ts
6175
- import fs3 from "fs";
6473
+ import fs4 from "fs";
6176
6474
  function getClient13() {
6177
6475
  return createApiClient();
6178
6476
  }
@@ -6263,7 +6561,7 @@ async function listQueries(project, format) {
6263
6561
  }
6264
6562
  }
6265
6563
  async function importQueries(project, filePath, format) {
6266
- if (!fs3.existsSync(filePath)) {
6564
+ if (!fs4.existsSync(filePath)) {
6267
6565
  throw new CliError({
6268
6566
  code: "QUERY_IMPORT_FILE_NOT_FOUND",
6269
6567
  message: `File not found: ${filePath}`,
@@ -6274,7 +6572,7 @@ async function importQueries(project, filePath, format) {
6274
6572
  }
6275
6573
  });
6276
6574
  }
6277
- const content = fs3.readFileSync(filePath, "utf-8");
6575
+ const content = fs4.readFileSync(filePath, "utf-8");
6278
6576
  const queries2 = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
6279
6577
  if (queries2.length === 0) {
6280
6578
  if (isMachineFormat(format)) {
@@ -6476,16 +6774,16 @@ var QUERY_CLI_COMMANDS = [
6476
6774
  ];
6477
6775
 
6478
6776
  // src/commands/mcp.ts
6479
- import fs4 from "fs";
6480
- import path2 from "path";
6777
+ import fs5 from "fs";
6778
+ import path3 from "path";
6481
6779
  import { createRequire } from "module";
6482
6780
 
6483
6781
  // src/mcp-clients.ts
6484
6782
  import os from "os";
6485
- import path from "path";
6783
+ import path2 from "path";
6486
6784
  var CLAUDE_DESKTOP_CONFIG_FILENAME = "claude_desktop_config.json";
6487
6785
  function homeRelative(...segments) {
6488
- return path.join(os.homedir(), ...segments);
6786
+ return path2.join(os.homedir(), ...segments);
6489
6787
  }
6490
6788
  function claudeDesktopConfigPath() {
6491
6789
  switch (process.platform) {
@@ -6493,7 +6791,7 @@ function claudeDesktopConfigPath() {
6493
6791
  return homeRelative("Library", "Application Support", "Claude", CLAUDE_DESKTOP_CONFIG_FILENAME);
6494
6792
  case "win32": {
6495
6793
  const appData = process.env.APPDATA ?? homeRelative("AppData", "Roaming");
6496
- return path.join(appData, "Claude", CLAUDE_DESKTOP_CONFIG_FILENAME);
6794
+ return path2.join(appData, "Claude", CLAUDE_DESKTOP_CONFIG_FILENAME);
6497
6795
  }
6498
6796
  default:
6499
6797
  return homeRelative(".config", "Claude", CLAUDE_DESKTOP_CONFIG_FILENAME);
@@ -6506,7 +6804,7 @@ function codexConfigPath() {
6506
6804
  return homeRelative(".codex", "config.toml");
6507
6805
  }
6508
6806
  function claudeCodeProjectConfigPath() {
6509
- return path.join(process.cwd(), ".mcp.json");
6807
+ return path2.join(process.cwd(), ".mcp.json");
6510
6808
  }
6511
6809
  var SUPPORTED_MCP_CLIENTS = [
6512
6810
  {
@@ -6549,7 +6847,7 @@ function listMcpClientIds() {
6549
6847
  var _require = createRequire(import.meta.url);
6550
6848
  function resolveCanonryMcpBin() {
6551
6849
  const packageJsonPath = _require.resolve("../package.json");
6552
- const packageRoot = path2.dirname(packageJsonPath);
6850
+ const packageRoot = path3.dirname(packageJsonPath);
6553
6851
  const pkg = _require("../package.json");
6554
6852
  const relativeBin = pkg.bin?.["canonry-mcp"];
6555
6853
  if (!relativeBin) {
@@ -6559,7 +6857,7 @@ function resolveCanonryMcpBin() {
6559
6857
  exitCode: 2
6560
6858
  });
6561
6859
  }
6562
- return path2.resolve(packageRoot, relativeBin);
6860
+ return path3.resolve(packageRoot, relativeBin);
6563
6861
  }
6564
6862
  function buildEntry(opts) {
6565
6863
  const target = opts.binPath ?? resolveCanonryMcpBin();
@@ -6592,8 +6890,8 @@ function renderClientSnippet(client, serverName, entry) {
6592
6890
  return renderJsonSnippet(serverName, entry, client.format);
6593
6891
  }
6594
6892
  function readJsonConfig(configPath) {
6595
- if (!fs4.existsSync(configPath)) return {};
6596
- const raw = fs4.readFileSync(configPath, "utf-8").trim();
6893
+ if (!fs5.existsSync(configPath)) return {};
6894
+ const raw = fs5.readFileSync(configPath, "utf-8").trim();
6597
6895
  if (!raw) return {};
6598
6896
  try {
6599
6897
  const parsed = JSON.parse(raw);
@@ -6611,14 +6909,14 @@ function readJsonConfig(configPath) {
6611
6909
  }
6612
6910
  }
6613
6911
  function writeJsonConfig(configPath, value) {
6614
- fs4.mkdirSync(path2.dirname(configPath), { recursive: true });
6615
- fs4.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
6912
+ fs5.mkdirSync(path3.dirname(configPath), { recursive: true });
6913
+ fs5.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
6616
6914
  `, "utf-8");
6617
6915
  }
6618
6916
  function backupConfigIfPresent(configPath) {
6619
- if (!fs4.existsSync(configPath)) return void 0;
6917
+ if (!fs5.existsSync(configPath)) return void 0;
6620
6918
  const backupPath = `${configPath}.canonry.bak`;
6621
- fs4.copyFileSync(configPath, backupPath);
6919
+ fs5.copyFileSync(configPath, backupPath);
6622
6920
  return backupPath;
6623
6921
  }
6624
6922
  function findClientOrThrow(id) {
@@ -6972,13 +7270,13 @@ var NOTIFY_CLI_COMMANDS = [
6972
7270
  ];
6973
7271
 
6974
7272
  // src/commands/apply.ts
6975
- import fs5 from "fs";
7273
+ import fs6 from "fs";
6976
7274
  import { parseAllDocuments } from "yaml";
6977
7275
  async function applyConfigFile(filePath) {
6978
- if (!fs5.existsSync(filePath)) {
7276
+ if (!fs6.existsSync(filePath)) {
6979
7277
  throw new Error(`File not found: ${filePath}`);
6980
7278
  }
6981
- const content = fs5.readFileSync(filePath, "utf-8");
7279
+ const content = fs6.readFileSync(filePath, "utf-8");
6982
7280
  const docs = parseAllDocuments(content);
6983
7281
  const client = createApiClient();
6984
7282
  const errors = [];
@@ -7893,11 +8191,11 @@ var PROJECT_CLI_COMMANDS = [
7893
8191
  ];
7894
8192
 
7895
8193
  // src/commands/report.ts
7896
- import fs6 from "fs";
7897
- import path3 from "path";
8194
+ import fs7 from "fs";
8195
+ import path4 from "path";
7898
8196
  function defaultOutputPath(project, audience) {
7899
8197
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
7900
- return path3.resolve(process.cwd(), `canonry-report-${project}-${audience}-${date}.html`);
8198
+ return path4.resolve(process.cwd(), `canonry-report-${project}-${audience}-${date}.html`);
7901
8199
  }
7902
8200
  async function runReportCommand(project, opts = {}) {
7903
8201
  const client = createApiClient();
@@ -7908,12 +8206,12 @@ async function runReportCommand(project, opts = {}) {
7908
8206
  return;
7909
8207
  }
7910
8208
  const html = renderReportHtml(report, { audience });
7911
- const targetPath = opts.output ? path3.resolve(opts.output) : defaultOutputPath(project, audience);
7912
- const dir = path3.dirname(targetPath);
7913
- if (!fs6.existsSync(dir)) {
7914
- fs6.mkdirSync(dir, { recursive: true });
8209
+ const targetPath = opts.output ? path4.resolve(opts.output) : defaultOutputPath(project, audience);
8210
+ const dir = path4.dirname(targetPath);
8211
+ if (!fs7.existsSync(dir)) {
8212
+ fs7.mkdirSync(dir, { recursive: true });
7915
8213
  }
7916
- fs6.writeFileSync(targetPath, html, "utf-8");
8214
+ fs7.writeFileSync(targetPath, html, "utf-8");
7917
8215
  console.log(`Report written to ${targetPath}`);
7918
8216
  }
7919
8217
 
@@ -8778,12 +9076,12 @@ var SKILLS_CLI_COMMANDS = [
8778
9076
  ];
8779
9077
 
8780
9078
  // src/commands/snapshot.ts
8781
- import fs8 from "fs";
8782
- import path5 from "path";
9079
+ import fs9 from "fs";
9080
+ import path6 from "path";
8783
9081
 
8784
9082
  // src/snapshot-pdf.ts
8785
- import fs7 from "fs";
8786
- import path4 from "path";
9083
+ import fs8 from "fs";
9084
+ import path5 from "path";
8787
9085
  import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
8788
9086
  var PAGE_WIDTH = 612;
8789
9087
  var PAGE_HEIGHT = 792;
@@ -8995,9 +9293,9 @@ async function writeSnapshotPdf(report, outputPath) {
8995
9293
  renderCompetitors(pdf, report);
8996
9294
  renderQueries(pdf, report);
8997
9295
  const bytes = await doc.save();
8998
- const resolvedPath = path4.resolve(outputPath);
8999
- fs7.mkdirSync(path4.dirname(resolvedPath), { recursive: true });
9000
- fs7.writeFileSync(resolvedPath, bytes);
9296
+ const resolvedPath = path5.resolve(outputPath);
9297
+ fs8.mkdirSync(path5.dirname(resolvedPath), { recursive: true });
9298
+ fs8.writeFileSync(resolvedPath, bytes);
9001
9299
  return resolvedPath;
9002
9300
  }
9003
9301
  function renderCover(pdf, report) {
@@ -9155,9 +9453,9 @@ Markdown saved: ${savedMdPath}`);
9155
9453
  PDF saved: ${savedPdfPath}`);
9156
9454
  }
9157
9455
  function writeSnapshotMarkdown(report, outputPath) {
9158
- const resolvedPath = path5.resolve(outputPath);
9159
- fs8.mkdirSync(path5.dirname(resolvedPath), { recursive: true });
9160
- fs8.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
9456
+ const resolvedPath = path6.resolve(outputPath);
9457
+ fs9.mkdirSync(path6.dirname(resolvedPath), { recursive: true });
9458
+ fs9.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
9161
9459
  return resolvedPath;
9162
9460
  }
9163
9461
  function formatSnapshotMarkdown(report) {
@@ -9449,7 +9747,7 @@ async function showOverview(project, opts) {
9449
9747
  console.log(JSON.stringify(overview, null, 2));
9450
9748
  return;
9451
9749
  }
9452
- renderHuman(overview);
9750
+ renderHuman2(overview);
9453
9751
  }
9454
9752
  async function showAllOverviews(opts) {
9455
9753
  const client = createApiClient();
@@ -9490,7 +9788,7 @@ function cell(value, width) {
9490
9788
  if (value.length >= width) return `${value.slice(0, width - 1)} `;
9491
9789
  return value.padEnd(width);
9492
9790
  }
9493
- function renderHuman(overview) {
9791
+ function renderHuman2(overview) {
9494
9792
  const {
9495
9793
  project: meta,
9496
9794
  latestRun,
@@ -10140,7 +10438,7 @@ var CONTENT_CLI_COMMANDS = [
10140
10438
 
10141
10439
  // src/commands/bootstrap.ts
10142
10440
  import crypto from "crypto";
10143
- import path6 from "path";
10441
+ import path7 from "path";
10144
10442
  import { eq } from "drizzle-orm";
10145
10443
 
10146
10444
  // ../config/src/index.ts
@@ -10297,7 +10595,7 @@ async function bootstrapCommand(_opts) {
10297
10595
  );
10298
10596
  }
10299
10597
  const configDir = getConfigDir();
10300
- const databasePath = env.databasePath || path6.join(configDir, "data.db");
10598
+ const databasePath = env.databasePath || path7.join(configDir, "data.db");
10301
10599
  const existing = configExists();
10302
10600
  const existingConfig = existing ? loadConfig() : void 0;
10303
10601
  let rawApiKey;
@@ -10367,10 +10665,10 @@ async function bootstrapCommand(_opts) {
10367
10665
 
10368
10666
  // src/commands/daemon.ts
10369
10667
  import { spawn } from "child_process";
10370
- import fs9 from "fs";
10371
- import path7 from "path";
10668
+ import fs10 from "fs";
10669
+ import path8 from "path";
10372
10670
  function getPidPath() {
10373
- return path7.join(getConfigDir(), "canonry.pid");
10671
+ return path8.join(getConfigDir(), "canonry.pid");
10374
10672
  }
10375
10673
  function isProcessAlive(pid) {
10376
10674
  try {
@@ -10410,8 +10708,8 @@ function buildServeForwardArgs(opts) {
10410
10708
  async function startDaemon(opts) {
10411
10709
  const pidPath = getPidPath();
10412
10710
  const format = opts.format ?? "text";
10413
- if (fs9.existsSync(pidPath)) {
10414
- const existingPid = parseInt(fs9.readFileSync(pidPath, "utf-8").trim(), 10);
10711
+ if (fs10.existsSync(pidPath)) {
10712
+ const existingPid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
10415
10713
  if (!isNaN(existingPid) && isProcessAlive(existingPid)) {
10416
10714
  throw new CliError({
10417
10715
  code: "DAEMON_ALREADY_RUNNING",
@@ -10422,9 +10720,9 @@ async function startDaemon(opts) {
10422
10720
  }
10423
10721
  });
10424
10722
  }
10425
- fs9.unlinkSync(pidPath);
10723
+ fs10.unlinkSync(pidPath);
10426
10724
  }
10427
- const cliPath = path7.resolve(new URL(import.meta.url).pathname);
10725
+ const cliPath = path8.resolve(new URL(import.meta.url).pathname);
10428
10726
  const inSourceMode = new URL(import.meta.url).pathname.endsWith(".ts");
10429
10727
  const args = inSourceMode ? ["--import", "tsx", cliPath, "serve"] : [cliPath, "serve"];
10430
10728
  args.push(...buildServeForwardArgs(opts));
@@ -10441,10 +10739,10 @@ async function startDaemon(opts) {
10441
10739
  });
10442
10740
  }
10443
10741
  const configDir = getConfigDir();
10444
- if (!fs9.existsSync(configDir)) {
10445
- fs9.mkdirSync(configDir, { recursive: true });
10742
+ if (!fs10.existsSync(configDir)) {
10743
+ fs10.mkdirSync(configDir, { recursive: true });
10446
10744
  }
10447
- fs9.writeFileSync(pidPath, String(child.pid), "utf-8");
10745
+ fs10.writeFileSync(pidPath, String(child.pid), "utf-8");
10448
10746
  const port = opts.port ?? "4100";
10449
10747
  const host = opts.host ?? "127.0.0.1";
10450
10748
  if (!isMachineFormat(format)) {
@@ -10453,7 +10751,7 @@ async function startDaemon(opts) {
10453
10751
  const ready = await waitForReady(host, port);
10454
10752
  if (!ready) {
10455
10753
  try {
10456
- fs9.unlinkSync(pidPath);
10754
+ fs10.unlinkSync(pidPath);
10457
10755
  } catch {
10458
10756
  }
10459
10757
  throw new CliError({
@@ -10485,7 +10783,7 @@ async function startDaemon(opts) {
10485
10783
  }
10486
10784
  function stopDaemon(format = "text") {
10487
10785
  const pidPath = getPidPath();
10488
- if (!fs9.existsSync(pidPath)) {
10786
+ if (!fs10.existsSync(pidPath)) {
10489
10787
  if (isMachineFormat(format)) {
10490
10788
  console.log(JSON.stringify({
10491
10789
  stopped: false,
@@ -10496,7 +10794,7 @@ function stopDaemon(format = "text") {
10496
10794
  console.log("Canonry is not running (no PID file found)");
10497
10795
  return;
10498
10796
  }
10499
- const pid = parseInt(fs9.readFileSync(pidPath, "utf-8").trim(), 10);
10797
+ const pid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
10500
10798
  if (isNaN(pid)) {
10501
10799
  if (isMachineFormat(format)) {
10502
10800
  console.log(JSON.stringify({
@@ -10507,7 +10805,7 @@ function stopDaemon(format = "text") {
10507
10805
  } else {
10508
10806
  console.error("Invalid PID file. Removing it.");
10509
10807
  }
10510
- fs9.unlinkSync(pidPath);
10808
+ fs10.unlinkSync(pidPath);
10511
10809
  return;
10512
10810
  }
10513
10811
  if (!isProcessAlive(pid)) {
@@ -10521,12 +10819,12 @@ function stopDaemon(format = "text") {
10521
10819
  } else {
10522
10820
  console.log(`Canonry is not running (stale PID: ${pid}). Cleaning up.`);
10523
10821
  }
10524
- fs9.unlinkSync(pidPath);
10822
+ fs10.unlinkSync(pidPath);
10525
10823
  return;
10526
10824
  }
10527
10825
  try {
10528
10826
  process.kill(pid, "SIGTERM");
10529
- fs9.unlinkSync(pidPath);
10827
+ fs10.unlinkSync(pidPath);
10530
10828
  if (isMachineFormat(format)) {
10531
10829
  console.log(JSON.stringify({
10532
10830
  stopped: true,
@@ -10550,9 +10848,9 @@ function stopDaemon(format = "text") {
10550
10848
 
10551
10849
  // src/commands/init.ts
10552
10850
  import crypto2 from "crypto";
10553
- import fs10 from "fs";
10851
+ import fs11 from "fs";
10554
10852
  import readline from "readline";
10555
- import path8 from "path";
10853
+ import path9 from "path";
10556
10854
  function prompt(question) {
10557
10855
  const rl = readline.createInterface({
10558
10856
  input: process.stdin,
@@ -10573,8 +10871,8 @@ var DEFAULT_QUOTA = {
10573
10871
  var PROJECT_MARKERS = [".git", "canonry.yaml", "canonry.yml", "package.json"];
10574
10872
  function cwdLooksLikeProject(dir) {
10575
10873
  const home = process.env.HOME ?? "";
10576
- if (home && path8.resolve(dir) === path8.resolve(home)) return false;
10577
- return PROJECT_MARKERS.some((marker) => fs10.existsSync(path8.join(dir, marker)));
10874
+ if (home && path9.resolve(dir) === path9.resolve(home)) return false;
10875
+ return PROJECT_MARKERS.some((marker) => fs11.existsSync(path9.join(dir, marker)));
10578
10876
  }
10579
10877
  var DEFAULT_AGENT_MODELS = {
10580
10878
  anthropic: "anthropic/claude-sonnet-4-6",
@@ -10605,8 +10903,8 @@ async function initCommand(opts) {
10605
10903
  return void 0;
10606
10904
  }
10607
10905
  const configDir = getConfigDir();
10608
- if (!fs10.existsSync(configDir)) {
10609
- fs10.mkdirSync(configDir, { recursive: true });
10906
+ if (!fs11.existsSync(configDir)) {
10907
+ fs11.mkdirSync(configDir, { recursive: true });
10610
10908
  }
10611
10909
  const bootstrapEnv = getBootstrapEnv(process.env, {
10612
10910
  GEMINI_API_KEY: opts?.geminiKey,
@@ -10721,7 +11019,7 @@ async function initCommand(opts) {
10721
11019
  const rawApiKey = `cnry_${crypto2.randomBytes(16).toString("hex")}`;
10722
11020
  const keyHash = crypto2.createHash("sha256").update(rawApiKey).digest("hex");
10723
11021
  const keyPrefix = rawApiKey.slice(0, 9);
10724
- const databasePath = path8.join(configDir, "data.db");
11022
+ const databasePath = path9.join(configDir, "data.db");
10725
11023
  const db = createClient(databasePath);
10726
11024
  migrate(db);
10727
11025
  db.insert(apiKeys).values({
@@ -11618,7 +11916,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
11618
11916
  ];
11619
11917
 
11620
11918
  // src/cli-commands/wordpress.ts
11621
- import fs11 from "fs";
11919
+ import fs12 from "fs";
11622
11920
 
11623
11921
  // src/commands/wordpress.ts
11624
11922
  function getClient26() {
@@ -11857,12 +12155,12 @@ async function wordpressSetMeta(project, body) {
11857
12155
  printPageDetail(result);
11858
12156
  }
11859
12157
  async function wordpressBulkSetMeta(project, opts) {
11860
- const fs12 = await import("fs/promises");
11861
- const path9 = await import("path");
11862
- const filePath = path9.resolve(opts.from);
12158
+ const fs13 = await import("fs/promises");
12159
+ const path10 = await import("path");
12160
+ const filePath = path10.resolve(opts.from);
11863
12161
  let raw;
11864
12162
  try {
11865
- raw = await fs12.readFile(filePath, "utf8");
12163
+ raw = await fs13.readFile(filePath, "utf8");
11866
12164
  } catch {
11867
12165
  throw new CliError({
11868
12166
  code: "FILE_READ_ERROR",
@@ -11959,13 +12257,13 @@ async function wordpressSetSchema(project, body) {
11959
12257
  printManualAssist(`Schema update for "${body.slug}"`, result);
11960
12258
  }
11961
12259
  async function wordpressSchemaDeploy(project, opts) {
11962
- const fs12 = await import("fs/promises");
11963
- const path9 = await import("path");
12260
+ const fs13 = await import("fs/promises");
12261
+ const path10 = await import("path");
11964
12262
  const yaml = await loadYamlModule();
11965
- const filePath = path9.resolve(opts.profile);
12263
+ const filePath = path10.resolve(opts.profile);
11966
12264
  let raw;
11967
12265
  try {
11968
- raw = await fs12.readFile(filePath, "utf8");
12266
+ raw = await fs13.readFile(filePath, "utf8");
11969
12267
  } catch {
11970
12268
  throw new CliError({
11971
12269
  code: "FILE_READ_ERROR",
@@ -12070,13 +12368,13 @@ async function wordpressOnboard(project, opts) {
12070
12368
  }
12071
12369
  let profileData;
12072
12370
  if (opts.profile) {
12073
- const fs12 = await import("fs/promises");
12074
- const path9 = await import("path");
12371
+ const fs13 = await import("fs/promises");
12372
+ const path10 = await import("path");
12075
12373
  const yaml = await loadYamlModule();
12076
- const filePath = path9.resolve(opts.profile);
12374
+ const filePath = path10.resolve(opts.profile);
12077
12375
  let raw;
12078
12376
  try {
12079
- raw = await fs12.readFile(filePath, "utf8");
12377
+ raw = await fs13.readFile(filePath, "utf8");
12080
12378
  } catch {
12081
12379
  throw new CliError({
12082
12380
  code: "FILE_READ_ERROR",
@@ -12225,7 +12523,7 @@ function resolveContent(input, command, usage, options) {
12225
12523
  }
12226
12524
  if (contentFile) {
12227
12525
  try {
12228
- return fs11.readFileSync(contentFile, "utf-8");
12526
+ return fs12.readFileSync(contentFile, "utf-8");
12229
12527
  } catch (error) {
12230
12528
  const message = error instanceof Error ? error.message : String(error);
12231
12529
  throw usageError(`Error: could not read --content-file "${contentFile}": ${message}`, {