@canonry/canonry 4.117.1 → 4.118.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 (30) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +74 -1
  2. package/assets/assets/AuditHistoryPanel-Yh7VEe4P.js +1 -0
  3. package/assets/assets/{BacklinksPage-Bkafm10m.js → BacklinksPage-BmO77kMs.js} +1 -1
  4. package/assets/assets/{ChartPrimitives-NV_GgqFn.js → ChartPrimitives-H0ICVpw_.js} +1 -1
  5. package/assets/assets/HistoryPage-DkLV_iRc.js +1 -0
  6. package/assets/assets/ProjectPage-R3odr_eA.js +7 -0
  7. package/assets/assets/{RunRow-df0d24S6.js → RunRow-BDH9agxQ.js} +1 -1
  8. package/assets/assets/RunsPage-D9YsEeT3.js +1 -0
  9. package/assets/assets/{SettingsPage-BKw6B6cd.js → SettingsPage-o5as3Ixw.js} +1 -1
  10. package/assets/assets/{TrafficPage-CzpiYHKj.js → TrafficPage-BCK203aQ.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-CC5nuqM1.js → TrafficSourceDetailPage-DsVMAZvS.js} +1 -1
  12. package/assets/assets/{arrow-left-CbQcW2pL.js → arrow-left-B7ZR6VC9.js} +1 -1
  13. package/assets/assets/{extract-error-message-CvqIZ-le.js → extract-error-message-DeYDUpew.js} +1 -1
  14. package/assets/assets/index-Bot6YiD6.css +1 -0
  15. package/assets/assets/index-QCFQv0xh.js +210 -0
  16. package/assets/assets/{trash-2-3J2u0woR.js → trash-2-xxHTqWbF.js} +1 -1
  17. package/assets/index.html +2 -2
  18. package/dist/{chunk-BMBHUFMI.js → chunk-75UBTCKS.js} +540 -16
  19. package/dist/{chunk-V4SW7SVX.js → chunk-CMZIPFNQ.js} +1598 -486
  20. package/dist/{chunk-NY7SC4ES.js → chunk-HGNY5GL4.js} +384 -15
  21. package/dist/{chunk-IAJ5TQ4S.js → chunk-KEZWLP4O.js} +1385 -1145
  22. package/dist/cli.js +390 -113
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-C5YLASIP.js → intelligence-service-FWPXMAVK.js} +2 -2
  25. package/dist/mcp.js +2 -2
  26. package/package.json +7 -7
  27. package/assets/assets/ProjectPage-0-NnRxys.js +0 -7
  28. package/assets/assets/RunsPage-CU6-4YTM.js +0 -1
  29. package/assets/assets/index-B4R1-8hR.css +0 -1
  30. package/assets/assets/index-LjcWHaNZ.js +0 -210
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setTelemetrySource,
30
30
  showFirstRunNotice,
31
31
  trackEvent
32
- } from "./chunk-NY7SC4ES.js";
32
+ } from "./chunk-HGNY5GL4.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-BMBHUFMI.js";
49
+ } from "./chunk-75UBTCKS.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-V4SW7SVX.js";
57
+ } from "./chunk-CMZIPFNQ.js";
58
58
  import {
59
59
  BacklinkSources,
60
60
  CcReleaseSyncStatuses,
@@ -65,6 +65,14 @@ import {
65
65
  REPORT_PERIOD_OPTIONS,
66
66
  RunStatuses,
67
67
  TrafficEventKinds,
68
+ adsAdCreateRequestSchema,
69
+ adsAdGroupCreateRequestSchema,
70
+ adsAdGroupUpdateRequestSchema,
71
+ adsAdUpdateRequestSchema,
72
+ adsCampaignCreateRequestSchema,
73
+ adsCampaignUpdateRequestSchema,
74
+ adsImageUploadRequestSchema,
75
+ adsPauseRequestSchema,
68
76
  backlinkSourceSchema,
69
77
  discoveryBucketSchema,
70
78
  discoveryCompetitorTypeSchema,
@@ -80,7 +88,7 @@ import {
80
88
  providerQuotaPolicySchema,
81
89
  resolveProviderInput,
82
90
  winnabilityClassSchema
83
- } from "./chunk-IAJ5TQ4S.js";
91
+ } from "./chunk-KEZWLP4O.js";
84
92
 
85
93
  // src/cli.ts
86
94
  import { pathToFileURL } from "url";
@@ -126,9 +134,9 @@ import { parseArgs } from "util";
126
134
  function commandId(spec) {
127
135
  return spec.path.join(".");
128
136
  }
129
- function matchesPath(args, path10) {
130
- if (args.length < path10.length) return false;
131
- return path10.every((segment, index) => args[index] === segment);
137
+ function matchesPath(args, path11) {
138
+ if (args.length < path11.length) return false;
139
+ return path11.every((segment, index) => args[index] === segment);
132
140
  }
133
141
  function withGlobalOptions(options) {
134
142
  const base = options ? { ...options } : {};
@@ -2713,9 +2721,46 @@ var DOCTOR_CLI_COMMANDS = [
2713
2721
  ];
2714
2722
 
2715
2723
  // src/commands/ads.ts
2724
+ import fs3 from "fs";
2716
2725
  function getClient5() {
2717
2726
  return createApiClient();
2718
2727
  }
2728
+ function readRequest(inputPath, schema) {
2729
+ if (!inputPath) {
2730
+ throw new CliError({
2731
+ code: "ADS_INPUT_REQUIRED",
2732
+ message: "A JSON input file is required",
2733
+ displayMessage: "Error: --input <json-file> is required (use --input - for stdin)"
2734
+ });
2735
+ }
2736
+ try {
2737
+ const raw = fs3.readFileSync(inputPath === "-" ? 0 : inputPath, "utf8");
2738
+ return schema.parse(JSON.parse(raw));
2739
+ } catch (err) {
2740
+ if (err instanceof CliError) throw err;
2741
+ throw new CliError({
2742
+ code: "ADS_INPUT_INVALID",
2743
+ message: err instanceof Error ? err.message : String(err),
2744
+ displayMessage: `Error: invalid ads JSON input (${err instanceof Error ? err.message : String(err)})`,
2745
+ details: { inputPath }
2746
+ });
2747
+ }
2748
+ }
2749
+ function printOperation(result, format) {
2750
+ if (isMachineFormat(format)) {
2751
+ console.log(JSON.stringify(result, null, 2));
2752
+ return;
2753
+ }
2754
+ const operation = result.operation;
2755
+ console.log(`${result.replayed ? "Replayed" : "Recorded"} ${operation.kind}: ${operation.state}`);
2756
+ console.log(`Operation: ${operation.operationKey}`);
2757
+ if (operation.entityId) console.log(`Entity: ${operation.entityType ?? "unknown"} ${operation.entityId}`);
2758
+ if (operation.upstreamUpdatedAt != null) console.log(`Updated: ${operation.upstreamUpdatedAt}`);
2759
+ if (operation.errorCode) console.log(`Error: ${operation.errorCode}: ${operation.errorMessage ?? ""}`);
2760
+ if (operation.state === "unknown") {
2761
+ console.log("Do not retry with a new operation key. Reconcile this outcome with a human first.");
2762
+ }
2763
+ }
2719
2764
  function describeConnection(status) {
2720
2765
  const lines = [];
2721
2766
  lines.push(`Connected: ${status.connected ? "yes" : "no"}`);
@@ -2768,6 +2813,49 @@ async function adsStatus(project, opts) {
2768
2813
  console.log("Connect with: canonry ads connect " + project + " --api-key <sdk-key>");
2769
2814
  }
2770
2815
  }
2816
+ async function adsOperationGet(project, opts) {
2817
+ printOperation(await getClient5().getAdsOperation(project, opts.operationKey), opts.format);
2818
+ }
2819
+ async function adsImageUpload(project, opts) {
2820
+ const request = readRequest(opts.input, adsImageUploadRequestSchema);
2821
+ printOperation(await getClient5().uploadAdsImage(project, request), opts.format);
2822
+ }
2823
+ async function adsCampaignCreate(project, opts) {
2824
+ const request = readRequest(opts.input, adsCampaignCreateRequestSchema);
2825
+ printOperation(await getClient5().createAdsCampaign(project, request), opts.format);
2826
+ }
2827
+ async function adsCampaignUpdate(project, campaignId, opts) {
2828
+ const request = readRequest(opts.input, adsCampaignUpdateRequestSchema);
2829
+ printOperation(await getClient5().updateAdsCampaign(project, campaignId, request), opts.format);
2830
+ }
2831
+ async function adsCampaignPause(project, campaignId, opts) {
2832
+ const request = readRequest(opts.input, adsPauseRequestSchema);
2833
+ printOperation(await getClient5().pauseAdsCampaign(project, campaignId, request), opts.format);
2834
+ }
2835
+ async function adsAdGroupCreate(project, opts) {
2836
+ const request = readRequest(opts.input, adsAdGroupCreateRequestSchema);
2837
+ printOperation(await getClient5().createAdsAdGroup(project, request), opts.format);
2838
+ }
2839
+ async function adsAdGroupUpdate(project, adGroupId, opts) {
2840
+ const request = readRequest(opts.input, adsAdGroupUpdateRequestSchema);
2841
+ printOperation(await getClient5().updateAdsAdGroup(project, adGroupId, request), opts.format);
2842
+ }
2843
+ async function adsAdGroupPause(project, adGroupId, opts) {
2844
+ const request = readRequest(opts.input, adsPauseRequestSchema);
2845
+ printOperation(await getClient5().pauseAdsAdGroup(project, adGroupId, request), opts.format);
2846
+ }
2847
+ async function adsAdCreate(project, opts) {
2848
+ const request = readRequest(opts.input, adsAdCreateRequestSchema);
2849
+ printOperation(await getClient5().createAdsAd(project, request), opts.format);
2850
+ }
2851
+ async function adsAdUpdate(project, adId, opts) {
2852
+ const request = readRequest(opts.input, adsAdUpdateRequestSchema);
2853
+ printOperation(await getClient5().updateAdsAd(project, adId, request), opts.format);
2854
+ }
2855
+ async function adsAdPause(project, adId, opts) {
2856
+ const request = readRequest(opts.input, adsPauseRequestSchema);
2857
+ printOperation(await getClient5().pauseAdsAd(project, adId, request), opts.format);
2858
+ }
2771
2859
  async function adsSync(project, opts) {
2772
2860
  const client = getClient5();
2773
2861
  const result = await client.triggerAdsSync(project);
@@ -2885,6 +2973,122 @@ var ADS_CLI_COMMANDS = [
2885
2973
  await adsStatus(project, { format: input.format });
2886
2974
  }
2887
2975
  },
2976
+ {
2977
+ path: ["ads", "operation"],
2978
+ usage: "canonry ads operation <project> <operation-key> [--format json]",
2979
+ run: async (input) => {
2980
+ const usage = "canonry ads operation <project> <operation-key> [--format json]";
2981
+ const project = requireProject(input, "ads.operation", usage);
2982
+ const operationKey = requirePositional(input, 1, {
2983
+ command: "ads.operation",
2984
+ usage,
2985
+ message: "operation key is required"
2986
+ });
2987
+ await adsOperationGet(project, { operationKey, format: input.format });
2988
+ }
2989
+ },
2990
+ {
2991
+ path: ["ads", "image", "upload"],
2992
+ usage: "canonry ads image upload <project> --input <json-file|-> [--format json]",
2993
+ options: { input: stringOption() },
2994
+ run: async (input) => {
2995
+ const project = requireProject(input, "ads.image.upload", "canonry ads image upload <project> --input <json-file|-> [--format json]");
2996
+ await adsImageUpload(project, { input: getString(input.values, "input"), format: input.format });
2997
+ }
2998
+ },
2999
+ {
3000
+ path: ["ads", "campaign", "create"],
3001
+ usage: "canonry ads campaign create <project> --input <json-file|-> [--format json]",
3002
+ options: { input: stringOption() },
3003
+ run: async (input) => {
3004
+ const project = requireProject(input, "ads.campaign.create", "canonry ads campaign create <project> --input <json-file|-> [--format json]");
3005
+ await adsCampaignCreate(project, { input: getString(input.values, "input"), format: input.format });
3006
+ }
3007
+ },
3008
+ {
3009
+ path: ["ads", "campaign", "update"],
3010
+ usage: "canonry ads campaign update <project> <campaign-id> --input <json-file|-> [--format json]",
3011
+ options: { input: stringOption() },
3012
+ run: async (input) => {
3013
+ const usage = "canonry ads campaign update <project> <campaign-id> --input <json-file|-> [--format json]";
3014
+ const project = requireProject(input, "ads.campaign.update", usage);
3015
+ const id = requirePositional(input, 1, { command: "ads.campaign.update", usage, message: "campaign id is required" });
3016
+ await adsCampaignUpdate(project, id, { input: getString(input.values, "input"), format: input.format });
3017
+ }
3018
+ },
3019
+ {
3020
+ path: ["ads", "campaign", "pause"],
3021
+ usage: "canonry ads campaign pause <project> <campaign-id> --input <json-file|-> [--format json]",
3022
+ options: { input: stringOption() },
3023
+ run: async (input) => {
3024
+ const usage = "canonry ads campaign pause <project> <campaign-id> --input <json-file|-> [--format json]";
3025
+ const project = requireProject(input, "ads.campaign.pause", usage);
3026
+ const id = requirePositional(input, 1, { command: "ads.campaign.pause", usage, message: "campaign id is required" });
3027
+ await adsCampaignPause(project, id, { input: getString(input.values, "input"), format: input.format });
3028
+ }
3029
+ },
3030
+ {
3031
+ path: ["ads", "ad-group", "create"],
3032
+ usage: "canonry ads ad-group create <project> --input <json-file|-> [--format json]",
3033
+ options: { input: stringOption() },
3034
+ run: async (input) => {
3035
+ const project = requireProject(input, "ads.ad-group.create", "canonry ads ad-group create <project> --input <json-file|-> [--format json]");
3036
+ await adsAdGroupCreate(project, { input: getString(input.values, "input"), format: input.format });
3037
+ }
3038
+ },
3039
+ {
3040
+ path: ["ads", "ad-group", "update"],
3041
+ usage: "canonry ads ad-group update <project> <ad-group-id> --input <json-file|-> [--format json]",
3042
+ options: { input: stringOption() },
3043
+ run: async (input) => {
3044
+ const usage = "canonry ads ad-group update <project> <ad-group-id> --input <json-file|-> [--format json]";
3045
+ const project = requireProject(input, "ads.ad-group.update", usage);
3046
+ const id = requirePositional(input, 1, { command: "ads.ad-group.update", usage, message: "ad group id is required" });
3047
+ await adsAdGroupUpdate(project, id, { input: getString(input.values, "input"), format: input.format });
3048
+ }
3049
+ },
3050
+ {
3051
+ path: ["ads", "ad-group", "pause"],
3052
+ usage: "canonry ads ad-group pause <project> <ad-group-id> --input <json-file|-> [--format json]",
3053
+ options: { input: stringOption() },
3054
+ run: async (input) => {
3055
+ const usage = "canonry ads ad-group pause <project> <ad-group-id> --input <json-file|-> [--format json]";
3056
+ const project = requireProject(input, "ads.ad-group.pause", usage);
3057
+ const id = requirePositional(input, 1, { command: "ads.ad-group.pause", usage, message: "ad group id is required" });
3058
+ await adsAdGroupPause(project, id, { input: getString(input.values, "input"), format: input.format });
3059
+ }
3060
+ },
3061
+ {
3062
+ path: ["ads", "ad", "create"],
3063
+ usage: "canonry ads ad create <project> --input <json-file|-> [--format json]",
3064
+ options: { input: stringOption() },
3065
+ run: async (input) => {
3066
+ const project = requireProject(input, "ads.ad.create", "canonry ads ad create <project> --input <json-file|-> [--format json]");
3067
+ await adsAdCreate(project, { input: getString(input.values, "input"), format: input.format });
3068
+ }
3069
+ },
3070
+ {
3071
+ path: ["ads", "ad", "update"],
3072
+ usage: "canonry ads ad update <project> <ad-id> --input <json-file|-> [--format json]",
3073
+ options: { input: stringOption() },
3074
+ run: async (input) => {
3075
+ const usage = "canonry ads ad update <project> <ad-id> --input <json-file|-> [--format json]";
3076
+ const project = requireProject(input, "ads.ad.update", usage);
3077
+ const id = requirePositional(input, 1, { command: "ads.ad.update", usage, message: "ad id is required" });
3078
+ await adsAdUpdate(project, id, { input: getString(input.values, "input"), format: input.format });
3079
+ }
3080
+ },
3081
+ {
3082
+ path: ["ads", "ad", "pause"],
3083
+ usage: "canonry ads ad pause <project> <ad-id> --input <json-file|-> [--format json]",
3084
+ options: { input: stringOption() },
3085
+ run: async (input) => {
3086
+ const usage = "canonry ads ad pause <project> <ad-id> --input <json-file|-> [--format json]";
3087
+ const project = requireProject(input, "ads.ad.pause", usage);
3088
+ const id = requirePositional(input, 1, { command: "ads.ad.pause", usage, message: "ad id is required" });
3089
+ await adsAdPause(project, id, { input: getString(input.values, "input"), format: input.format });
3090
+ }
3091
+ },
2888
3092
  {
2889
3093
  path: ["ads", "sync"],
2890
3094
  usage: "canonry ads sync <project> [--format json]",
@@ -2948,9 +3152,9 @@ async function gaConnect(project, opts) {
2948
3152
  propertyId: opts.propertyId
2949
3153
  };
2950
3154
  if (opts.keyFile) {
2951
- const fs13 = await import("fs");
3155
+ const fs15 = await import("fs");
2952
3156
  try {
2953
- const content = fs13.readFileSync(opts.keyFile, "utf-8");
3157
+ const content = fs15.readFileSync(opts.keyFile, "utf-8");
2954
3158
  JSON.parse(content);
2955
3159
  body.keyJson = content;
2956
3160
  } catch (e) {
@@ -4202,9 +4406,9 @@ async function getCommand(opts) {
4202
4406
  console.log(JSON.stringify(leaf, null, 2));
4203
4407
  }
4204
4408
  }
4205
- function walkPath(value, path10) {
4206
- if (!path10 || path10 === ".") return value;
4207
- const segments = path10.split(".").flatMap((part) => {
4409
+ function walkPath(value, path11) {
4410
+ if (!path11 || path11 === ".") return value;
4411
+ const segments = path11.split(".").flatMap((part) => {
4208
4412
  const tokens = [];
4209
4413
  let i = 0;
4210
4414
  const bracketStart = part.indexOf("[");
@@ -4252,13 +4456,13 @@ var GET_CLI_COMMANDS = [
4252
4456
  },
4253
4457
  run: async (input) => {
4254
4458
  const project = requireProject(input, "get", USAGE2);
4255
- const path10 = requirePositional(input, 1, {
4459
+ const path11 = requirePositional(input, 1, {
4256
4460
  command: "get",
4257
4461
  usage: USAGE2,
4258
4462
  message: 'path is required (e.g. "scores.mentionShare.value")'
4259
4463
  });
4260
4464
  const from = getString(input.values, "from");
4261
- await getCommand({ project, path: path10, from, format: input.format });
4465
+ await getCommand({ project, path: path11, from, format: input.format });
4262
4466
  }
4263
4467
  }
4264
4468
  ];
@@ -4297,9 +4501,9 @@ async function trafficConnectWordpress(project, opts) {
4297
4501
  }
4298
4502
  let applicationPassword = opts.appPassword?.trim() ?? "";
4299
4503
  if (!applicationPassword && opts.appPasswordFile) {
4300
- const fs13 = await import("fs");
4504
+ const fs15 = await import("fs");
4301
4505
  try {
4302
- applicationPassword = fs13.readFileSync(opts.appPasswordFile, "utf-8").trim();
4506
+ applicationPassword = fs15.readFileSync(opts.appPasswordFile, "utf-8").trim();
4303
4507
  } catch (e) {
4304
4508
  const msg = e instanceof Error ? e.message : String(e);
4305
4509
  throw new CliError({
@@ -4355,10 +4559,10 @@ async function trafficConnectCloudRun(project, opts) {
4355
4559
  details: { project }
4356
4560
  });
4357
4561
  }
4358
- const fs13 = await import("fs");
4562
+ const fs15 = await import("fs");
4359
4563
  let keyJson;
4360
4564
  try {
4361
- keyJson = fs13.readFileSync(opts.serviceAccountKey, "utf-8");
4565
+ keyJson = fs15.readFileSync(opts.serviceAccountKey, "utf-8");
4362
4566
  JSON.parse(keyJson);
4363
4567
  } catch (e) {
4364
4568
  const msg = e instanceof Error ? e.message : String(e);
@@ -4418,9 +4622,9 @@ async function trafficConnectVercel(project, opts) {
4418
4622
  }
4419
4623
  let token = opts.token?.trim() ?? "";
4420
4624
  if (!token && opts.tokenFile) {
4421
- const fs13 = await import("fs");
4625
+ const fs15 = await import("fs");
4422
4626
  try {
4423
- token = fs13.readFileSync(opts.tokenFile, "utf-8").trim();
4627
+ token = fs15.readFileSync(opts.tokenFile, "utf-8").trim();
4424
4628
  } catch (e) {
4425
4629
  const msg = e instanceof Error ? e.message : String(e);
4426
4630
  throw new CliError({
@@ -6238,7 +6442,7 @@ var KEYS_CLI_COMMANDS = [
6238
6442
  ];
6239
6443
 
6240
6444
  // src/commands/keyword.ts
6241
- import fs3 from "fs";
6445
+ import fs4 from "fs";
6242
6446
  function getClient12() {
6243
6447
  return createApiClient();
6244
6448
  }
@@ -6306,7 +6510,7 @@ async function listKeywords(project, format) {
6306
6510
  }
6307
6511
  }
6308
6512
  async function importKeywords(project, filePath, format) {
6309
- if (!fs3.existsSync(filePath)) {
6513
+ if (!fs4.existsSync(filePath)) {
6310
6514
  throw new CliError({
6311
6515
  code: "KEYWORD_IMPORT_FILE_NOT_FOUND",
6312
6516
  message: `File not found: ${filePath}`,
@@ -6317,7 +6521,7 @@ async function importKeywords(project, filePath, format) {
6317
6521
  }
6318
6522
  });
6319
6523
  }
6320
- const content = fs3.readFileSync(filePath, "utf-8");
6524
+ const content = fs4.readFileSync(filePath, "utf-8");
6321
6525
  const keywords = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
6322
6526
  if (keywords.length === 0) {
6323
6527
  if (isMachineFormat(format)) {
@@ -6518,7 +6722,7 @@ var KEYWORD_CLI_COMMANDS = [
6518
6722
  ];
6519
6723
 
6520
6724
  // src/commands/query.ts
6521
- import fs4 from "fs";
6725
+ import fs5 from "fs";
6522
6726
  function getClient13() {
6523
6727
  return createApiClient();
6524
6728
  }
@@ -6609,7 +6813,7 @@ async function listQueries(project, format) {
6609
6813
  }
6610
6814
  }
6611
6815
  async function importQueries(project, filePath, format) {
6612
- if (!fs4.existsSync(filePath)) {
6816
+ if (!fs5.existsSync(filePath)) {
6613
6817
  throw new CliError({
6614
6818
  code: "QUERY_IMPORT_FILE_NOT_FOUND",
6615
6819
  message: `File not found: ${filePath}`,
@@ -6620,7 +6824,7 @@ async function importQueries(project, filePath, format) {
6620
6824
  }
6621
6825
  });
6622
6826
  }
6623
- const content = fs4.readFileSync(filePath, "utf-8");
6827
+ const content = fs5.readFileSync(filePath, "utf-8");
6624
6828
  const queries2 = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
6625
6829
  if (queries2.length === 0) {
6626
6830
  if (isMachineFormat(format)) {
@@ -6822,7 +7026,7 @@ var QUERY_CLI_COMMANDS = [
6822
7026
  ];
6823
7027
 
6824
7028
  // src/commands/mcp.ts
6825
- import fs5 from "fs";
7029
+ import fs6 from "fs";
6826
7030
  import path3 from "path";
6827
7031
  import { createRequire } from "module";
6828
7032
 
@@ -6938,8 +7142,8 @@ function renderClientSnippet(client, serverName, entry) {
6938
7142
  return renderJsonSnippet(serverName, entry, client.format);
6939
7143
  }
6940
7144
  function readJsonConfig(configPath) {
6941
- if (!fs5.existsSync(configPath)) return {};
6942
- const raw = fs5.readFileSync(configPath, "utf-8").trim();
7145
+ if (!fs6.existsSync(configPath)) return {};
7146
+ const raw = fs6.readFileSync(configPath, "utf-8").trim();
6943
7147
  if (!raw) return {};
6944
7148
  try {
6945
7149
  const parsed = JSON.parse(raw);
@@ -6957,14 +7161,14 @@ function readJsonConfig(configPath) {
6957
7161
  }
6958
7162
  }
6959
7163
  function writeJsonConfig(configPath, value) {
6960
- fs5.mkdirSync(path3.dirname(configPath), { recursive: true });
6961
- fs5.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
7164
+ fs6.mkdirSync(path3.dirname(configPath), { recursive: true });
7165
+ fs6.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
6962
7166
  `, "utf-8");
6963
7167
  }
6964
7168
  function backupConfigIfPresent(configPath) {
6965
- if (!fs5.existsSync(configPath)) return void 0;
7169
+ if (!fs6.existsSync(configPath)) return void 0;
6966
7170
  const backupPath = `${configPath}.canonry.bak`;
6967
- fs5.copyFileSync(configPath, backupPath);
7171
+ fs6.copyFileSync(configPath, backupPath);
6968
7172
  return backupPath;
6969
7173
  }
6970
7174
  function findClientOrThrow(id) {
@@ -7318,13 +7522,13 @@ var NOTIFY_CLI_COMMANDS = [
7318
7522
  ];
7319
7523
 
7320
7524
  // src/commands/apply.ts
7321
- import fs6 from "fs";
7525
+ import fs7 from "fs";
7322
7526
  import { parseAllDocuments } from "yaml";
7323
7527
  async function applyConfigFile(filePath) {
7324
- if (!fs6.existsSync(filePath)) {
7528
+ if (!fs7.existsSync(filePath)) {
7325
7529
  throw new Error(`File not found: ${filePath}`);
7326
7530
  }
7327
- const content = fs6.readFileSync(filePath, "utf-8");
7531
+ const content = fs7.readFileSync(filePath, "utf-8");
7328
7532
  const docs = parseAllDocuments(content);
7329
7533
  const client = createApiClient();
7330
7534
  const errors = [];
@@ -7641,43 +7845,68 @@ async function loadLatestRunForExport(client, project) {
7641
7845
  return client.getRun(latestRun.id);
7642
7846
  }
7643
7847
 
7848
+ // src/commands/results-export.ts
7849
+ import fs8 from "fs";
7850
+ import path4 from "path";
7851
+ async function exportResults(project, opts) {
7852
+ const { output, ...request } = opts;
7853
+ const artifact = await createApiClient().downloadResultsExport(project, request);
7854
+ if (output === "-") {
7855
+ process.stdout.write(artifact.content);
7856
+ return;
7857
+ }
7858
+ const target = output ? path4.resolve(output) : path4.resolve(process.cwd(), path4.basename(artifact.filename));
7859
+ fs8.mkdirSync(path4.dirname(target), { recursive: true });
7860
+ fs8.writeFileSync(target, artifact.content, "utf8");
7861
+ console.log(`Results export written to ${target}`);
7862
+ }
7863
+
7644
7864
  // src/commands/history.ts
7645
7865
  function getClient18() {
7646
7866
  return createApiClient();
7647
7867
  }
7648
- async function showHistory(project, format) {
7868
+ function originLabel(entry) {
7869
+ const userAgent = entry.userAgent?.toLowerCase() ?? "";
7870
+ if (userAgent.includes("canonry-mcp")) return "mcp";
7871
+ if (userAgent.includes("canonry-cli")) return "cli";
7872
+ if (userAgent.includes("mozilla/")) return "dashboard";
7873
+ return entry.actor;
7874
+ }
7875
+ async function showHistory(project, format, opts = {}) {
7649
7876
  const client = getClient18();
7650
7877
  try {
7651
- const entries = await client.getHistory(project);
7878
+ const entries = project ? await client.getHistory(project, opts) : await client.getGlobalHistory(opts);
7652
7879
  if (format === "json") {
7653
7880
  console.log(JSON.stringify(entries, null, 2));
7654
7881
  return;
7655
7882
  }
7656
7883
  if (format === "jsonl") {
7657
- emitJsonl(entries.map((entry) => ({ project, ...entry })));
7884
+ emitJsonl(entries.map((entry) => ({ project: project ?? null, ...entry })));
7658
7885
  return;
7659
7886
  }
7660
7887
  if (entries.length === 0) {
7661
- console.log(`No audit history for "${project}".`);
7888
+ console.log(project ? `No audit history for "${project}".` : "No instance audit history.");
7662
7889
  return;
7663
7890
  }
7664
- console.log(`Audit history for "${project}" (${entries.length}):
7891
+ console.log(`${project ? `Audit history for "${project}"` : "Instance audit history"} (${entries.length}):
7665
7892
  `);
7666
- console.log(" TIMESTAMP ACTION ENTITY TYPE ACTOR");
7667
- console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500");
7893
+ console.log(" TIMESTAMP ACTION ENTITY TYPE ORIGIN");
7894
+ console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7668
7895
  for (const entry of entries) {
7669
7896
  console.log(
7670
- ` ${entry.createdAt.padEnd(23)} ${entry.action.padEnd(18)} ${entry.entityType.padEnd(11)} ${entry.actor}`
7897
+ ` ${entry.createdAt.padEnd(23)} ${entry.action.padEnd(18)} ${entry.entityType.padEnd(11)} ${originLabel(entry)}`
7671
7898
  );
7899
+ if (entry.actorSession) console.log(` session: ${entry.actorSession}`);
7900
+ if (entry.diff != null) console.log(` diff: ${JSON.stringify(entry.diff)}`);
7672
7901
  }
7673
7902
  } catch (err) {
7674
7903
  const message = err instanceof Error ? err.message : String(err);
7675
7904
  throw new CliError({
7676
7905
  code: "HISTORY_FETCH_FAILED",
7677
- message: `Failed to fetch history for project "${project}"`,
7906
+ message: project ? `Failed to fetch history for project "${project}"` : "Failed to fetch instance history",
7678
7907
  displayMessage: `Failed to fetch history: ${message}`,
7679
7908
  details: {
7680
- project,
7909
+ project: project ?? null,
7681
7910
  cause: message
7682
7911
  }
7683
7912
  });
@@ -7746,7 +7975,35 @@ async function getLatestRunSummary(client, project) {
7746
7975
  }
7747
7976
 
7748
7977
  // src/cli-commands/operator.ts
7978
+ var RESULTS_EXPORT_USAGE = "canonry results export <project> [--format json|csv] [--since <ISO>] [--until <ISO>] [--include-probes] [--output <path>|-]";
7979
+ function parseResultsExportFormat(value) {
7980
+ if (value === void 0 || value === "json") return "json";
7981
+ if (value === "csv") return "csv";
7982
+ throw usageError(`Error: --format must be "json" or "csv"
7983
+
7984
+ Usage: ${RESULTS_EXPORT_USAGE}`);
7985
+ }
7749
7986
  var OPERATOR_CLI_COMMANDS = [
7987
+ {
7988
+ path: ["results", "export"],
7989
+ usage: RESULTS_EXPORT_USAGE,
7990
+ options: {
7991
+ since: stringOption(),
7992
+ until: stringOption(),
7993
+ "include-probes": { type: "boolean", default: false },
7994
+ output: { type: "string", short: "o" }
7995
+ },
7996
+ run: async (input) => {
7997
+ const project = requireProject(input, "results export", RESULTS_EXPORT_USAGE);
7998
+ await exportResults(project, {
7999
+ format: parseResultsExportFormat(getString(input.values, "format")),
8000
+ since: getString(input.values, "since"),
8001
+ until: getString(input.values, "until"),
8002
+ includeProbes: getBoolean(input.values, "include-probes"),
8003
+ output: getString(input.values, "output")
8004
+ });
8005
+ }
8006
+ },
7750
8007
  {
7751
8008
  path: ["status"],
7752
8009
  usage: "canonry status <project> [--format json]",
@@ -7765,10 +8022,25 @@ var OPERATOR_CLI_COMMANDS = [
7765
8022
  },
7766
8023
  {
7767
8024
  path: ["history"],
7768
- usage: "canonry history <project> [--format json]",
8025
+ usage: "canonry history <project> [--limit <n>] [--since <ISO>] [--action <action>] [--actor <actor>] [--entity-type <type>] [--format json|jsonl]\n canonry history --all [same filters]",
8026
+ options: {
8027
+ all: { type: "boolean", default: false },
8028
+ limit: stringOption(),
8029
+ since: stringOption(),
8030
+ action: stringOption(),
8031
+ actor: stringOption(),
8032
+ "entity-type": stringOption()
8033
+ },
7769
8034
  run: async (input) => {
7770
- const project = requireProject(input, "history", "canonry history <project> [--format json]");
7771
- await showHistory(project, input.format);
8035
+ const usage = "canonry history <project> [--limit <n>] [--since <ISO>] [--action <action>] [--actor <actor>] [--entity-type <type>] [--format json|jsonl]\n canonry history --all [same filters]";
8036
+ const project = getBoolean(input.values, "all") ? void 0 : requireProject(input, "history", usage);
8037
+ await showHistory(project, input.format, {
8038
+ limit: parseIntegerOption(input, "limit", { command: "history", usage, message: "--limit must be an integer" }),
8039
+ since: getString(input.values, "since"),
8040
+ action: getString(input.values, "action"),
8041
+ actor: getString(input.values, "actor"),
8042
+ entityType: getString(input.values, "entity-type")
8043
+ });
7772
8044
  }
7773
8045
  },
7774
8046
  {
@@ -8239,11 +8511,11 @@ var PROJECT_CLI_COMMANDS = [
8239
8511
  ];
8240
8512
 
8241
8513
  // src/commands/report.ts
8242
- import fs7 from "fs";
8243
- import path4 from "path";
8514
+ import fs9 from "fs";
8515
+ import path5 from "path";
8244
8516
  function defaultOutputPath(project, audience) {
8245
8517
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8246
- return path4.resolve(process.cwd(), `canonry-report-${project}-${audience}-${date}.html`);
8518
+ return path5.resolve(process.cwd(), `canonry-report-${project}-${audience}-${date}.html`);
8247
8519
  }
8248
8520
  async function runReportCommand(project, opts = {}) {
8249
8521
  const client = createApiClient();
@@ -8254,12 +8526,12 @@ async function runReportCommand(project, opts = {}) {
8254
8526
  return;
8255
8527
  }
8256
8528
  const html = renderReportHtml(report, { audience });
8257
- const targetPath = opts.output ? path4.resolve(opts.output) : defaultOutputPath(project, audience);
8258
- const dir = path4.dirname(targetPath);
8259
- if (!fs7.existsSync(dir)) {
8260
- fs7.mkdirSync(dir, { recursive: true });
8529
+ const targetPath = opts.output ? path5.resolve(opts.output) : defaultOutputPath(project, audience);
8530
+ const dir = path5.dirname(targetPath);
8531
+ if (!fs9.existsSync(dir)) {
8532
+ fs9.mkdirSync(dir, { recursive: true });
8261
8533
  }
8262
- fs7.writeFileSync(targetPath, html, "utf-8");
8534
+ fs9.writeFileSync(targetPath, html, "utf-8");
8263
8535
  console.log(`Report written to ${targetPath}`);
8264
8536
  }
8265
8537
 
@@ -9124,12 +9396,12 @@ var SKILLS_CLI_COMMANDS = [
9124
9396
  ];
9125
9397
 
9126
9398
  // src/commands/snapshot.ts
9127
- import fs9 from "fs";
9128
- import path6 from "path";
9399
+ import fs11 from "fs";
9400
+ import path7 from "path";
9129
9401
 
9130
9402
  // src/snapshot-pdf.ts
9131
- import fs8 from "fs";
9132
- import path5 from "path";
9403
+ import fs10 from "fs";
9404
+ import path6 from "path";
9133
9405
  import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
9134
9406
  var PAGE_WIDTH = 612;
9135
9407
  var PAGE_HEIGHT = 792;
@@ -9341,9 +9613,9 @@ async function writeSnapshotPdf(report, outputPath) {
9341
9613
  renderCompetitors(pdf, report);
9342
9614
  renderQueries(pdf, report);
9343
9615
  const bytes = await doc.save();
9344
- const resolvedPath = path5.resolve(outputPath);
9345
- fs8.mkdirSync(path5.dirname(resolvedPath), { recursive: true });
9346
- fs8.writeFileSync(resolvedPath, bytes);
9616
+ const resolvedPath = path6.resolve(outputPath);
9617
+ fs10.mkdirSync(path6.dirname(resolvedPath), { recursive: true });
9618
+ fs10.writeFileSync(resolvedPath, bytes);
9347
9619
  return resolvedPath;
9348
9620
  }
9349
9621
  function renderCover(pdf, report) {
@@ -9501,9 +9773,9 @@ Markdown saved: ${savedMdPath}`);
9501
9773
  PDF saved: ${savedPdfPath}`);
9502
9774
  }
9503
9775
  function writeSnapshotMarkdown(report, outputPath) {
9504
- const resolvedPath = path6.resolve(outputPath);
9505
- fs9.mkdirSync(path6.dirname(resolvedPath), { recursive: true });
9506
- fs9.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
9776
+ const resolvedPath = path7.resolve(outputPath);
9777
+ fs11.mkdirSync(path7.dirname(resolvedPath), { recursive: true });
9778
+ fs11.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
9507
9779
  return resolvedPath;
9508
9780
  }
9509
9781
  function formatSnapshotMarkdown(report) {
@@ -10486,7 +10758,7 @@ var CONTENT_CLI_COMMANDS = [
10486
10758
 
10487
10759
  // src/commands/bootstrap.ts
10488
10760
  import crypto from "crypto";
10489
- import path7 from "path";
10761
+ import path8 from "path";
10490
10762
  import { eq } from "drizzle-orm";
10491
10763
 
10492
10764
  // ../config/src/index.ts
@@ -10643,7 +10915,7 @@ async function bootstrapCommand(_opts) {
10643
10915
  );
10644
10916
  }
10645
10917
  const configDir = getConfigDir();
10646
- const databasePath = env.databasePath || path7.join(configDir, "data.db");
10918
+ const databasePath = env.databasePath || path8.join(configDir, "data.db");
10647
10919
  const existing = configExists();
10648
10920
  const existingConfig = existing ? loadConfig() : void 0;
10649
10921
  let rawApiKey;
@@ -10713,10 +10985,10 @@ async function bootstrapCommand(_opts) {
10713
10985
 
10714
10986
  // src/commands/daemon.ts
10715
10987
  import { spawn } from "child_process";
10716
- import fs10 from "fs";
10717
- import path8 from "path";
10988
+ import fs12 from "fs";
10989
+ import path9 from "path";
10718
10990
  function getPidPath() {
10719
- return path8.join(getConfigDir(), "canonry.pid");
10991
+ return path9.join(getConfigDir(), "canonry.pid");
10720
10992
  }
10721
10993
  function isProcessAlive(pid) {
10722
10994
  try {
@@ -10756,8 +11028,8 @@ function buildServeForwardArgs(opts) {
10756
11028
  async function startDaemon(opts) {
10757
11029
  const pidPath = getPidPath();
10758
11030
  const format = opts.format ?? "text";
10759
- if (fs10.existsSync(pidPath)) {
10760
- const existingPid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
11031
+ if (fs12.existsSync(pidPath)) {
11032
+ const existingPid = parseInt(fs12.readFileSync(pidPath, "utf-8").trim(), 10);
10761
11033
  if (!isNaN(existingPid) && isProcessAlive(existingPid)) {
10762
11034
  throw new CliError({
10763
11035
  code: "DAEMON_ALREADY_RUNNING",
@@ -10768,9 +11040,9 @@ async function startDaemon(opts) {
10768
11040
  }
10769
11041
  });
10770
11042
  }
10771
- fs10.unlinkSync(pidPath);
11043
+ fs12.unlinkSync(pidPath);
10772
11044
  }
10773
- const cliPath = path8.resolve(new URL(import.meta.url).pathname);
11045
+ const cliPath = path9.resolve(new URL(import.meta.url).pathname);
10774
11046
  const inSourceMode = new URL(import.meta.url).pathname.endsWith(".ts");
10775
11047
  const args = inSourceMode ? ["--import", "tsx", cliPath, "serve"] : [cliPath, "serve"];
10776
11048
  args.push(...buildServeForwardArgs(opts));
@@ -10787,10 +11059,10 @@ async function startDaemon(opts) {
10787
11059
  });
10788
11060
  }
10789
11061
  const configDir = getConfigDir();
10790
- if (!fs10.existsSync(configDir)) {
10791
- fs10.mkdirSync(configDir, { recursive: true });
11062
+ if (!fs12.existsSync(configDir)) {
11063
+ fs12.mkdirSync(configDir, { recursive: true });
10792
11064
  }
10793
- fs10.writeFileSync(pidPath, String(child.pid), "utf-8");
11065
+ fs12.writeFileSync(pidPath, String(child.pid), "utf-8");
10794
11066
  const port = opts.port ?? "4100";
10795
11067
  const host = opts.host ?? "127.0.0.1";
10796
11068
  if (!isMachineFormat(format)) {
@@ -10799,7 +11071,7 @@ async function startDaemon(opts) {
10799
11071
  const ready = await waitForReady(host, port);
10800
11072
  if (!ready) {
10801
11073
  try {
10802
- fs10.unlinkSync(pidPath);
11074
+ fs12.unlinkSync(pidPath);
10803
11075
  } catch {
10804
11076
  }
10805
11077
  throw new CliError({
@@ -10831,7 +11103,7 @@ async function startDaemon(opts) {
10831
11103
  }
10832
11104
  function stopDaemon(format = "text") {
10833
11105
  const pidPath = getPidPath();
10834
- if (!fs10.existsSync(pidPath)) {
11106
+ if (!fs12.existsSync(pidPath)) {
10835
11107
  if (isMachineFormat(format)) {
10836
11108
  console.log(JSON.stringify({
10837
11109
  stopped: false,
@@ -10842,7 +11114,7 @@ function stopDaemon(format = "text") {
10842
11114
  console.log("Canonry is not running (no PID file found)");
10843
11115
  return;
10844
11116
  }
10845
- const pid = parseInt(fs10.readFileSync(pidPath, "utf-8").trim(), 10);
11117
+ const pid = parseInt(fs12.readFileSync(pidPath, "utf-8").trim(), 10);
10846
11118
  if (isNaN(pid)) {
10847
11119
  if (isMachineFormat(format)) {
10848
11120
  console.log(JSON.stringify({
@@ -10853,7 +11125,7 @@ function stopDaemon(format = "text") {
10853
11125
  } else {
10854
11126
  console.error("Invalid PID file. Removing it.");
10855
11127
  }
10856
- fs10.unlinkSync(pidPath);
11128
+ fs12.unlinkSync(pidPath);
10857
11129
  return;
10858
11130
  }
10859
11131
  if (!isProcessAlive(pid)) {
@@ -10867,12 +11139,12 @@ function stopDaemon(format = "text") {
10867
11139
  } else {
10868
11140
  console.log(`Canonry is not running (stale PID: ${pid}). Cleaning up.`);
10869
11141
  }
10870
- fs10.unlinkSync(pidPath);
11142
+ fs12.unlinkSync(pidPath);
10871
11143
  return;
10872
11144
  }
10873
11145
  try {
10874
11146
  process.kill(pid, "SIGTERM");
10875
- fs10.unlinkSync(pidPath);
11147
+ fs12.unlinkSync(pidPath);
10876
11148
  if (isMachineFormat(format)) {
10877
11149
  console.log(JSON.stringify({
10878
11150
  stopped: true,
@@ -10896,9 +11168,9 @@ function stopDaemon(format = "text") {
10896
11168
 
10897
11169
  // src/commands/init.ts
10898
11170
  import crypto2 from "crypto";
10899
- import fs11 from "fs";
11171
+ import fs13 from "fs";
10900
11172
  import readline from "readline";
10901
- import path9 from "path";
11173
+ import path10 from "path";
10902
11174
  function prompt(question) {
10903
11175
  const rl = readline.createInterface({
10904
11176
  input: process.stdin,
@@ -10919,8 +11191,8 @@ var DEFAULT_QUOTA = {
10919
11191
  var PROJECT_MARKERS = [".git", "canonry.yaml", "canonry.yml", "package.json"];
10920
11192
  function cwdLooksLikeProject(dir) {
10921
11193
  const home = process.env.HOME ?? "";
10922
- if (home && path9.resolve(dir) === path9.resolve(home)) return false;
10923
- return PROJECT_MARKERS.some((marker) => fs11.existsSync(path9.join(dir, marker)));
11194
+ if (home && path10.resolve(dir) === path10.resolve(home)) return false;
11195
+ return PROJECT_MARKERS.some((marker) => fs13.existsSync(path10.join(dir, marker)));
10924
11196
  }
10925
11197
  var DEFAULT_AGENT_MODELS = {
10926
11198
  anthropic: "anthropic/claude-sonnet-4-6",
@@ -10951,8 +11223,8 @@ async function initCommand(opts) {
10951
11223
  return void 0;
10952
11224
  }
10953
11225
  const configDir = getConfigDir();
10954
- if (!fs11.existsSync(configDir)) {
10955
- fs11.mkdirSync(configDir, { recursive: true });
11226
+ if (!fs13.existsSync(configDir)) {
11227
+ fs13.mkdirSync(configDir, { recursive: true });
10956
11228
  }
10957
11229
  const bootstrapEnv = getBootstrapEnv(process.env, {
10958
11230
  GEMINI_API_KEY: opts?.geminiKey,
@@ -11067,7 +11339,7 @@ async function initCommand(opts) {
11067
11339
  const rawApiKey = `cnry_${crypto2.randomBytes(16).toString("hex")}`;
11068
11340
  const keyHash = crypto2.createHash("sha256").update(rawApiKey).digest("hex");
11069
11341
  const keyPrefix = rawApiKey.slice(0, 9);
11070
- const databasePath = path9.join(configDir, "data.db");
11342
+ const databasePath = path10.join(configDir, "data.db");
11071
11343
  const db = createClient(databasePath);
11072
11344
  migrate(db);
11073
11345
  db.insert(apiKeys).values({
@@ -11619,7 +11891,7 @@ function getClient25() {
11619
11891
  }
11620
11892
  async function technicalAeoScore(project, opts) {
11621
11893
  const client = getClient25();
11622
- const score = await client.getTechnicalAeoScore(project);
11894
+ const score = await client.getTechnicalAeoScore(project, { runId: opts.runId });
11623
11895
  if (isMachineFormat(opts.format)) {
11624
11896
  console.log(JSON.stringify(score, null, 2));
11625
11897
  return;
@@ -11656,7 +11928,7 @@ async function technicalAeoScore(project, opts) {
11656
11928
  async function technicalAeoPages(project, opts) {
11657
11929
  const client = getClient25();
11658
11930
  const status = opts.status === "success" || opts.status === "error" ? opts.status : void 0;
11659
- const res = await client.getTechnicalAeoPages(project, { status, sort: opts.sort, limit: opts.limit });
11931
+ const res = await client.getTechnicalAeoPages(project, { runId: opts.runId, status, sort: opts.sort, limit: opts.limit });
11660
11932
  if (opts.format === "jsonl") {
11661
11933
  emitJsonl(res.pages.map((p) => ({ project, runId: res.runId, ...p })));
11662
11934
  return;
@@ -11740,28 +12012,33 @@ async function technicalAeoRun(project, opts) {
11740
12012
  var TECHNICAL_AEO_CLI_COMMANDS = [
11741
12013
  {
11742
12014
  path: ["technical-aeo", "score"],
11743
- usage: "canonry technical-aeo score <project> [--format json]",
12015
+ usage: "canonry technical-aeo score <project> [--run-id <id>] [--format json]",
12016
+ options: {
12017
+ "run-id": stringOption()
12018
+ },
11744
12019
  run: async (input) => {
11745
12020
  const project = requireProject(
11746
12021
  input,
11747
12022
  "technical-aeo.score",
11748
- "canonry technical-aeo score <project> [--format json]"
12023
+ "canonry technical-aeo score <project> [--run-id <id>] [--format json]"
11749
12024
  );
11750
- await technicalAeoScore(project, { format: input.format });
12025
+ await technicalAeoScore(project, { runId: getString(input.values, "run-id"), format: input.format });
11751
12026
  }
11752
12027
  },
11753
12028
  {
11754
12029
  path: ["technical-aeo", "pages"],
11755
- usage: "canonry technical-aeo pages <project> [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]",
12030
+ usage: "canonry technical-aeo pages <project> [--run-id <id>] [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]",
11756
12031
  options: {
12032
+ "run-id": stringOption(),
11757
12033
  status: stringOption(),
11758
12034
  sort: stringOption(),
11759
12035
  limit: stringOption()
11760
12036
  },
11761
12037
  run: async (input) => {
11762
- const usage = "canonry technical-aeo pages <project> [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]";
12038
+ const usage = "canonry technical-aeo pages <project> [--run-id <id>] [--status success|error] [--sort score-asc|score-desc|url] [--limit <n>] [--format json|jsonl]";
11763
12039
  const project = requireProject(input, "technical-aeo.pages", usage);
11764
12040
  await technicalAeoPages(project, {
12041
+ runId: getString(input.values, "run-id"),
11765
12042
  status: getString(input.values, "status"),
11766
12043
  sort: getString(input.values, "sort"),
11767
12044
  limit: parseIntegerOption(input, "limit", {
@@ -12053,7 +12330,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
12053
12330
  ];
12054
12331
 
12055
12332
  // src/cli-commands/wordpress.ts
12056
- import fs12 from "fs";
12333
+ import fs14 from "fs";
12057
12334
 
12058
12335
  // src/commands/wordpress.ts
12059
12336
  function getClient26() {
@@ -12292,12 +12569,12 @@ async function wordpressSetMeta(project, body) {
12292
12569
  printPageDetail(result);
12293
12570
  }
12294
12571
  async function wordpressBulkSetMeta(project, opts) {
12295
- const fs13 = await import("fs/promises");
12296
- const path10 = await import("path");
12297
- const filePath = path10.resolve(opts.from);
12572
+ const fs15 = await import("fs/promises");
12573
+ const path11 = await import("path");
12574
+ const filePath = path11.resolve(opts.from);
12298
12575
  let raw;
12299
12576
  try {
12300
- raw = await fs13.readFile(filePath, "utf8");
12577
+ raw = await fs15.readFile(filePath, "utf8");
12301
12578
  } catch {
12302
12579
  throw new CliError({
12303
12580
  code: "FILE_READ_ERROR",
@@ -12394,13 +12671,13 @@ async function wordpressSetSchema(project, body) {
12394
12671
  printManualAssist(`Schema update for "${body.slug}"`, result);
12395
12672
  }
12396
12673
  async function wordpressSchemaDeploy(project, opts) {
12397
- const fs13 = await import("fs/promises");
12398
- const path10 = await import("path");
12674
+ const fs15 = await import("fs/promises");
12675
+ const path11 = await import("path");
12399
12676
  const yaml = await loadYamlModule();
12400
- const filePath = path10.resolve(opts.profile);
12677
+ const filePath = path11.resolve(opts.profile);
12401
12678
  let raw;
12402
12679
  try {
12403
- raw = await fs13.readFile(filePath, "utf8");
12680
+ raw = await fs15.readFile(filePath, "utf8");
12404
12681
  } catch {
12405
12682
  throw new CliError({
12406
12683
  code: "FILE_READ_ERROR",
@@ -12505,13 +12782,13 @@ async function wordpressOnboard(project, opts) {
12505
12782
  }
12506
12783
  let profileData;
12507
12784
  if (opts.profile) {
12508
- const fs13 = await import("fs/promises");
12509
- const path10 = await import("path");
12785
+ const fs15 = await import("fs/promises");
12786
+ const path11 = await import("path");
12510
12787
  const yaml = await loadYamlModule();
12511
- const filePath = path10.resolve(opts.profile);
12788
+ const filePath = path11.resolve(opts.profile);
12512
12789
  let raw;
12513
12790
  try {
12514
- raw = await fs13.readFile(filePath, "utf8");
12791
+ raw = await fs15.readFile(filePath, "utf8");
12515
12792
  } catch {
12516
12793
  throw new CliError({
12517
12794
  code: "FILE_READ_ERROR",
@@ -12660,7 +12937,7 @@ function resolveContent(input, command, usage, options) {
12660
12937
  }
12661
12938
  if (contentFile) {
12662
12939
  try {
12663
- return fs12.readFileSync(contentFile, "utf-8");
12940
+ return fs14.readFileSync(contentFile, "utf-8");
12664
12941
  } catch (error) {
12665
12942
  const message = error instanceof Error ? error.message : String(error);
12666
12943
  throw usageError(`Error: could not read --content-file "${contentFile}": ${message}`, {