@ainyc/canonry 4.100.0 → 4.100.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 (26) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +0 -12
  2. package/assets/assets/{BacklinksPage-DWZdWEm3.js → BacklinksPage-v2RC8wlg.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-C-ky5206.js → ChartPrimitives-B74e5pqn.js} +1 -1
  4. package/assets/assets/{ProjectPage-CpbFpi6J.js → ProjectPage-BCzS7TQn.js} +4 -4
  5. package/assets/assets/{RunRow-Bj-D4kZe.js → RunRow-BmVPjO-m.js} +1 -1
  6. package/assets/assets/{RunsPage-GktitsAV.js → RunsPage-CK5atXvL.js} +1 -1
  7. package/assets/assets/{SettingsPage-AsFLFDS3.js → SettingsPage-DarPFUPl.js} +1 -1
  8. package/assets/assets/{TrafficPage-Cf3uCkxs.js → TrafficPage-Ddnn_WqU.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-B5t7nf9C.js → TrafficSourceDetailPage-g08SKnwZ.js} +1 -1
  10. package/assets/assets/{arrow-left-CZFQuQO_.js → arrow-left-D39Vxasb.js} +1 -1
  11. package/assets/assets/{extract-error-message--bieZ2IX.js → extract-error-message-BiNWqBeh.js} +1 -1
  12. package/assets/assets/index-BCuWbxUj.css +1 -0
  13. package/assets/assets/index-Dd4J1VhB.js +210 -0
  14. package/assets/assets/{trash-2-sKO0k75f.js → trash-2-xh6gsnap.js} +1 -1
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-74SOIAIY.js → chunk-ALJSES3X.js} +4 -4
  17. package/dist/{chunk-UVIHWF45.js → chunk-IDI6LMYL.js} +1 -27
  18. package/dist/{chunk-ADLS64PG.js → chunk-JF7EXHGA.js} +0 -105
  19. package/dist/{chunk-SNHYRSUF.js → chunk-YBIT5O62.js} +12 -366
  20. package/dist/cli.js +4 -110
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-3CRNJLUZ.js → intelligence-service-TWCEKVKZ.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +9 -9
  25. package/assets/assets/index-9hI0ODQU.css +0 -1
  26. package/assets/assets/index-Cb2h7KkD.js +0 -210
@@ -18,7 +18,6 @@ import {
18
18
  DiscoveryBuckets,
19
19
  DiscoveryCompetitorTypes,
20
20
  DiscoverySessionStatuses,
21
- PortfolioChangeTypes,
22
21
  RunKinds,
23
22
  RunStatuses,
24
23
  RunTriggers,
@@ -132,7 +131,6 @@ import {
132
131
  formatIsoDate,
133
132
  formatNumber,
134
133
  formatRatio,
135
- formatRunErrorOneLine,
136
134
  formatWindowCountDelta,
137
135
  ga4AiReferralHistoryEntrySchema,
138
136
  ga4SessionHistoryEntrySchema,
@@ -186,7 +184,6 @@ import {
186
184
  parseRunError,
187
185
  parseWindow,
188
186
  pickClusterRepresentative,
189
- portfolioDtoSchema,
190
187
  projectConfigSchema,
191
188
  projectDtoSchema,
192
189
  projectOverviewDtoSchema,
@@ -266,10 +263,10 @@ import {
266
263
  wordpressSchemaDeployResultDtoSchema,
267
264
  wordpressSchemaStatusResultDtoSchema,
268
265
  wordpressStatusDtoSchema
269
- } from "./chunk-ADLS64PG.js";
266
+ } from "./chunk-JF7EXHGA.js";
270
267
 
271
268
  // src/intelligence-service.ts
272
- import { eq as eq37, desc as desc18, asc as asc6, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
269
+ import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
273
270
 
274
271
  // ../db/src/client.ts
275
272
  import { mkdirSync } from "fs";
@@ -5048,233 +5045,6 @@ function buildRunHistory(runs2, snapshotsByRunId, limit = DEFAULT_RUN_HISTORY_LI
5048
5045
  });
5049
5046
  }
5050
5047
 
5051
- // ../intelligence/src/portfolio-change-feed.ts
5052
- var PORTFOLIO_CHANGE_FEED_LIMIT = 12;
5053
- var TONE_SEVERITY = {
5054
- negative: 0,
5055
- caution: 1,
5056
- positive: 2,
5057
- neutral: 3
5058
- };
5059
- function pluralizeQueries(n) {
5060
- return n === 1 ? "query" : "queries";
5061
- }
5062
- function pluralizeAnswers(n) {
5063
- return n === 1 ? "answer" : "answers";
5064
- }
5065
- function affectedDetail(queries2, max = 3) {
5066
- const list = queries2 ?? [];
5067
- if (list.length === 0) return "";
5068
- const shown = list.slice(0, max).map((q) => `"${q}"`).join(", ");
5069
- const remaining = list.length - max;
5070
- return remaining > 0 ? `${shown} +${remaining} more` : shown;
5071
- }
5072
- function buildProjectChanges(input) {
5073
- const {
5074
- projectName,
5075
- projectSlug,
5076
- citationMovement,
5077
- mentionMovement,
5078
- movementComparison,
5079
- attentionItems,
5080
- latestRun
5081
- } = input;
5082
- const href = `/projects/${encodeURIComponent(projectSlug)}`;
5083
- const rows = [];
5084
- if (!latestRun) {
5085
- rows.push({
5086
- id: `${projectSlug}:${PortfolioChangeTypes["project-never-run"]}`,
5087
- projectName,
5088
- projectSlug,
5089
- changeType: PortfolioChangeTypes["project-never-run"],
5090
- tone: "neutral",
5091
- title: `${projectName} has no completed sweep yet`,
5092
- detail: `${input.trackedQueryCount} ${pluralizeQueries(input.trackedQueryCount)} tracked \u2014 run a sweep to start measuring.`,
5093
- occurredAt: input.projectCreatedAt,
5094
- href,
5095
- actionLabel: "Run sweep",
5096
- comparable: false
5097
- });
5098
- return rows;
5099
- }
5100
- const { runId, occurredAt } = latestRun;
5101
- const comparable = movementComparison.comparable;
5102
- if (latestRun.status === RunStatuses.failed) {
5103
- rows.push({
5104
- id: `${projectSlug}:${PortfolioChangeTypes["run-failed"]}:${runId}`,
5105
- projectName,
5106
- projectSlug,
5107
- changeType: PortfolioChangeTypes["run-failed"],
5108
- tone: "negative",
5109
- title: `${projectName} sweep failed`,
5110
- detail: latestRun.error ? formatRunErrorOneLine(latestRun.error) : "The latest visibility sweep failed.",
5111
- occurredAt,
5112
- href,
5113
- actionLabel: "View run",
5114
- comparable
5115
- });
5116
- }
5117
- if (comparable) {
5118
- if (citationMovement.lost > 0) {
5119
- rows.push({
5120
- id: `${projectSlug}:${PortfolioChangeTypes["citation-lost"]}:${runId}`,
5121
- projectName,
5122
- projectSlug,
5123
- changeType: PortfolioChangeTypes["citation-lost"],
5124
- tone: "negative",
5125
- title: `${projectName} lost ${citationMovement.lost} cited ${pluralizeQueries(citationMovement.lost)}`,
5126
- detail: affectedDetail(citationMovement.lostQueries),
5127
- occurredAt,
5128
- href,
5129
- actionLabel: "Open project",
5130
- comparable: true
5131
- });
5132
- }
5133
- if (citationMovement.gained > 0) {
5134
- rows.push({
5135
- id: `${projectSlug}:${PortfolioChangeTypes["citation-gained"]}:${runId}`,
5136
- projectName,
5137
- projectSlug,
5138
- changeType: PortfolioChangeTypes["citation-gained"],
5139
- tone: "positive",
5140
- title: `${projectName} gained ${citationMovement.gained} cited ${pluralizeQueries(citationMovement.gained)}`,
5141
- detail: affectedDetail(citationMovement.gainedQueries),
5142
- occurredAt,
5143
- href,
5144
- actionLabel: "Open project",
5145
- comparable: true
5146
- });
5147
- }
5148
- if (mentionMovement.lost > 0) {
5149
- const queries2 = affectedDetail(mentionMovement.lostQueries);
5150
- rows.push({
5151
- id: `${projectSlug}:${PortfolioChangeTypes["mention-lost"]}:${runId}`,
5152
- projectName,
5153
- projectSlug,
5154
- changeType: PortfolioChangeTypes["mention-lost"],
5155
- tone: "negative",
5156
- title: `${projectName} dropped from ${mentionMovement.lost} ${pluralizeAnswers(mentionMovement.lost)}`,
5157
- detail: queries2 ? `No longer mentioned for ${queries2}` : "",
5158
- occurredAt,
5159
- href,
5160
- actionLabel: "Open project",
5161
- comparable: true
5162
- });
5163
- }
5164
- if (mentionMovement.gained > 0) {
5165
- rows.push({
5166
- id: `${projectSlug}:${PortfolioChangeTypes["mention-gained"]}:${runId}`,
5167
- projectName,
5168
- projectSlug,
5169
- changeType: PortfolioChangeTypes["mention-gained"],
5170
- tone: "positive",
5171
- title: `${projectName} now mentioned in ${mentionMovement.gained} more ${pluralizeAnswers(mentionMovement.gained)}`,
5172
- detail: affectedDetail(mentionMovement.gainedQueries),
5173
- occurredAt,
5174
- href,
5175
- actionLabel: "Open project",
5176
- comparable: true
5177
- });
5178
- }
5179
- } else if (movementComparison.hasPreviousRun && movementComparison.querySetChanged) {
5180
- rows.push({
5181
- id: `${projectSlug}:${PortfolioChangeTypes["query-set-changed"]}:${runId}`,
5182
- projectName,
5183
- projectSlug,
5184
- changeType: PortfolioChangeTypes["query-set-changed"],
5185
- tone: "neutral",
5186
- title: `${projectName} query set changed`,
5187
- detail: `+${movementComparison.addedQueryCount} added \xB7 \u2212${movementComparison.removedQueryCount} removed since last sweep \u2014 movement compares the shared queries`,
5188
- occurredAt,
5189
- href,
5190
- actionLabel: "Open project",
5191
- comparable: false
5192
- });
5193
- }
5194
- for (const item of attentionItems) {
5195
- if (item.id.startsWith("insight_")) {
5196
- const isCritical = item.tone === "negative";
5197
- const changeType = isCritical ? PortfolioChangeTypes["insight-critical"] : PortfolioChangeTypes["insight-high"];
5198
- rows.push({
5199
- id: `${projectSlug}:${changeType}:${item.id}`,
5200
- projectName,
5201
- projectSlug,
5202
- changeType,
5203
- tone: item.tone,
5204
- title: item.title,
5205
- detail: item.detail,
5206
- occurredAt,
5207
- href,
5208
- actionLabel: isCritical ? "Critical" : "High",
5209
- comparable
5210
- });
5211
- } else if (item.id === "stale_visibility") {
5212
- rows.push({
5213
- id: `${projectSlug}:${PortfolioChangeTypes["stale-visibility"]}:${runId}`,
5214
- projectName,
5215
- projectSlug,
5216
- changeType: PortfolioChangeTypes["stale-visibility"],
5217
- tone: "caution",
5218
- title: `${projectName} visibility data is stale`,
5219
- detail: "Integration syncs have run since the last sweep.",
5220
- occurredAt,
5221
- href,
5222
- actionLabel: "Re-sweep",
5223
- comparable
5224
- });
5225
- }
5226
- }
5227
- return rows;
5228
- }
5229
- function resolveEmptyState(projectCount, comparableProjectCount) {
5230
- if (comparableProjectCount === 0) {
5231
- return {
5232
- kind: "awaiting-second-sweep",
5233
- title: "No changes to compare yet",
5234
- detail: "Visibility movement appears after a second sweep."
5235
- };
5236
- }
5237
- return {
5238
- kind: "all-clear",
5239
- title: "No changes since the last sweep",
5240
- detail: `All ${projectCount} project${projectCount === 1 ? "" : "s"} held their mention and citation coverage.`
5241
- };
5242
- }
5243
- function buildPortfolioChangeFeed(inputs, _nowIso) {
5244
- const all = [];
5245
- let comparableProjectCount = 0;
5246
- let firstSweepProjectCount = 0;
5247
- for (const input of inputs) {
5248
- if (input.latestRun) {
5249
- if (input.movementComparison.comparable) comparableProjectCount += 1;
5250
- if (!input.movementComparison.hasPreviousRun) firstSweepProjectCount += 1;
5251
- }
5252
- all.push(...buildProjectChanges(input));
5253
- }
5254
- const byId = /* @__PURE__ */ new Map();
5255
- for (const row of all) {
5256
- if (!byId.has(row.id)) byId.set(row.id, row);
5257
- }
5258
- const deduped = [...byId.values()];
5259
- deduped.sort((a, b) => {
5260
- if (a.occurredAt !== b.occurredAt) return a.occurredAt < b.occurredAt ? 1 : -1;
5261
- const severity = TONE_SEVERITY[a.tone] - TONE_SEVERITY[b.tone];
5262
- if (severity !== 0) return severity;
5263
- if (a.projectName !== b.projectName) return a.projectName < b.projectName ? -1 : 1;
5264
- return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
5265
- });
5266
- const changeFeedTotal = deduped.length;
5267
- const changeFeed = deduped.slice(0, PORTFOLIO_CHANGE_FEED_LIMIT);
5268
- const feedEmptyState = changeFeedTotal === 0 ? resolveEmptyState(inputs.length, comparableProjectCount) : null;
5269
- return {
5270
- changeFeed,
5271
- changeFeedTotal,
5272
- feedEmptyState,
5273
- comparableProjectCount,
5274
- firstSweepProjectCount
5275
- };
5276
- }
5277
-
5278
5048
  // ../intelligence/src/provider-trends.ts
5279
5049
  function buildProviderTrends(runs2, snapshotsByRunId, limit = 12) {
5280
5050
  const recent = [...runs2].sort((a, b) => b.createdAt.localeCompare(a.createdAt)).slice(0, limit).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
@@ -13337,9 +13107,8 @@ async function visibilityStatsRoutes(app) {
13337
13107
  }
13338
13108
 
13339
13109
  // ../api-routes/src/composites.ts
13340
- import { eq as eq17, and as and12, asc as asc2, desc as desc9, sql as sql7, like as like2, or as or4, inArray as inArray9 } from "drizzle-orm";
13110
+ import { eq as eq17, and as and12, desc as desc9, sql as sql7, like as like2, or as or4, inArray as inArray9 } from "drizzle-orm";
13341
13111
  var TOP_INSIGHT_LIMIT = 5;
13342
- var PORTFOLIO_RECENT_RUNS_LIMIT = 8;
13343
13112
  var SEARCH_HIT_HARD_LIMIT = 50;
13344
13113
  var SEARCH_SNIPPET_RADIUS = 80;
13345
13114
  var INTEGRATION_SYNC_KINDS = /* @__PURE__ */ new Set([
@@ -13356,14 +13125,6 @@ async function compositeRoutes(app) {
13356
13125
  const project = resolveProject(app.db, request.params.name);
13357
13126
  const filterLocation = (request.query.location ?? "").trim() || null;
13358
13127
  const sinceIso = parseSinceFilter(request.query.since);
13359
- return reply.send(computeProjectOverview(project, { filterLocation, sinceIso }));
13360
- });
13361
- app.get("/portfolio", async (_request, reply) => {
13362
- return reply.send(buildPortfolioOverview());
13363
- });
13364
- function computeProjectOverview(project, opts = {}) {
13365
- const filterLocation = opts.filterLocation ?? null;
13366
- const sinceIso = opts.sinceIso ?? null;
13367
13128
  const allRunsRaw = app.db.select().from(runs).where(and12(eq17(runs.projectId, project.id), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).all();
13368
13129
  const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
13369
13130
  const totalRuns = allRuns.length;
@@ -13496,111 +13257,8 @@ async function compositeRoutes(app) {
13496
13257
  dateRangeLabel: "All time",
13497
13258
  contextLabel: `${project.country} / ${project.language.toUpperCase()}`
13498
13259
  };
13499
- return result;
13500
- }
13501
- function buildPortfolioOverview() {
13502
- const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
13503
- const projectRows = app.db.select().from(projects).orderBy(asc2(projects.name)).all();
13504
- const trackedCountRows = app.db.select({ projectId: queries.projectId, total: sql7`COUNT(*)` }).from(queries).groupBy(queries.projectId).all();
13505
- const trackedCountByProject = new Map(trackedCountRows.map((r) => [r.projectId, Number(r.total)]));
13506
- const lastSweepRow = app.db.select({ createdAt: runs.createdAt, finishedAt: runs.finishedAt }).from(runs).where(and12(
13507
- eq17(runs.kind, RunKinds["answer-visibility"]),
13508
- notProbeRun(),
13509
- inArray9(runs.status, [RunStatuses.completed, RunStatuses.partial])
13510
- )).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(1).get();
13511
- const lastSweepAt = lastSweepRow ? lastSweepRow.finishedAt ?? lastSweepRow.createdAt : null;
13512
- const feedInputs = [];
13513
- const projectRowDtos = [];
13514
- const runHistoryById = /* @__PURE__ */ new Map();
13515
- for (const projectRow of projectRows) {
13516
- const overview = computeProjectOverview(projectRow);
13517
- for (const point of overview.runHistory) runHistoryById.set(point.runId, point);
13518
- const latestVisRunRow = app.db.select().from(runs).where(and12(
13519
- eq17(runs.projectId, projectRow.id),
13520
- eq17(runs.kind, RunKinds["answer-visibility"]),
13521
- notProbeRun()
13522
- )).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(1).get();
13523
- const projectName = projectRow.displayName || projectRow.name;
13524
- feedInputs.push({
13525
- projectName,
13526
- projectSlug: projectRow.name,
13527
- citationMovement: overview.citationMovement,
13528
- mentionMovement: overview.mentionMovement,
13529
- movementComparison: overview.movementComparison,
13530
- attentionItems: overview.attentionItems,
13531
- latestRun: latestVisRunRow ? {
13532
- runId: latestVisRunRow.id,
13533
- status: latestVisRunRow.status,
13534
- occurredAt: latestVisRunRow.finishedAt ?? latestVisRunRow.createdAt,
13535
- error: parseRunError(latestVisRunRow.error)
13536
- } : null,
13537
- trackedQueryCount: trackedCountByProject.get(projectRow.id) ?? 0,
13538
- projectCreatedAt: projectRow.createdAt
13539
- });
13540
- const mention = overview.scores.mention;
13541
- projectRowDtos.push({
13542
- projectSlug: projectRow.name,
13543
- projectName,
13544
- canonicalDomain: projectRow.canonicalDomain,
13545
- mentionScore: mention.progress ?? 0,
13546
- mentionTone: mention.tone,
13547
- mentionedOfTotal: { mentioned: overview.queryCounts.mentionedQueries, total: overview.queryCounts.totalQueries },
13548
- citedOfTotal: { cited: overview.queryCounts.citedQueries, total: overview.queryCounts.totalQueries },
13549
- mentionDelta: {
13550
- gained: overview.mentionMovement.gained,
13551
- lost: overview.mentionMovement.lost,
13552
- comparable: overview.movementComparison.comparable
13553
- },
13554
- citationDelta: {
13555
- gained: overview.citationMovement.gained,
13556
- lost: overview.citationMovement.lost,
13557
- comparable: overview.movementComparison.comparable
13558
- },
13559
- competitorPressureLabel: overview.scores.competitorPressure.value,
13560
- mentionTrend: mention.trend,
13561
- lastRunAt: latestVisRunRow ? latestVisRunRow.finishedAt ?? latestVisRunRow.createdAt : null,
13562
- hasEverRun: latestVisRunRow != null
13563
- });
13564
- }
13565
- const feed = buildPortfolioChangeFeed(feedInputs, generatedAt);
13566
- const projectById = new Map(projectRows.map((p) => [p.id, p]));
13567
- const recentRunRows = app.db.select().from(runs).where(and12(eq17(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).limit(PORTFOLIO_RECENT_RUNS_LIMIT).all();
13568
- const recentRuns = [];
13569
- for (const run of recentRunRows) {
13570
- const projectRow = projectById.get(run.projectId);
13571
- if (!projectRow) continue;
13572
- const point = runHistoryById.get(run.id);
13573
- const countable = run.status === RunStatuses.completed || run.status === RunStatuses.partial;
13574
- const error = parseRunError(run.error);
13575
- recentRuns.push({
13576
- runId: run.id,
13577
- projectName: projectRow.displayName || projectRow.name,
13578
- projectSlug: projectRow.name,
13579
- kindLabel: "Answer visibility sweep",
13580
- status: run.status,
13581
- createdAt: run.createdAt,
13582
- startedAt: run.startedAt ?? null,
13583
- finishedAt: run.finishedAt ?? null,
13584
- durationMs: run.startedAt && run.finishedAt ? new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime() : null,
13585
- mentionedCount: countable && point ? point.mentionedCount : null,
13586
- citedCount: countable && point ? point.citedCount : null,
13587
- totalCount: countable && point ? point.totalCount : null,
13588
- errorSummary: error ? formatRunErrorOneLine(error) : null
13589
- });
13590
- }
13591
- return {
13592
- generatedAt,
13593
- lastSweepAt,
13594
- projectCount: projectRows.length,
13595
- comparableProjectCount: feed.comparableProjectCount,
13596
- firstSweepProjectCount: feed.firstSweepProjectCount,
13597
- changeFeed: feed.changeFeed,
13598
- changeFeedTotal: feed.changeFeedTotal,
13599
- feedEmptyState: feed.feedEmptyState,
13600
- recentRuns,
13601
- projects: projectRowDtos
13602
- };
13603
- }
13260
+ return reply.send(result);
13261
+ });
13604
13262
  app.get("/projects/:name/search", async (request, reply) => {
13605
13263
  const project = resolveProject(app.db, request.params.name);
13606
13264
  const rawQuery = (request.query.q ?? "").trim();
@@ -14227,7 +13885,6 @@ var SCHEMA_TABLE = {
14227
13885
  LatestProjectRunDto: latestProjectRunDtoSchema,
14228
13886
  LocationContext: locationContextSchema,
14229
13887
  NotificationDto: notificationDtoSchema,
14230
- PortfolioDto: portfolioDtoSchema,
14231
13888
  ProjectDto: projectDtoSchema,
14232
13889
  ProjectOverviewDto: projectOverviewDtoSchema,
14233
13890
  ProjectReportDto: projectReportDtoSchema,
@@ -17482,17 +17139,6 @@ var routeCatalog = [
17482
17139
  404: errorResponse("Project not found.")
17483
17140
  }
17484
17141
  },
17485
- {
17486
- method: "get",
17487
- path: "/api/v1/portfolio",
17488
- summary: "Cross-project portfolio: what changed, recent runs, project state",
17489
- description: 'One call for the dashboard Portfolio page and `canonry portfolio`. Returns a server-ordered "what changed" feed (citation/mention gains and losses over each project\'s comparable basket, failed sweeps, critical/high insight echoes, stale-visibility, query-set changes, and never-run projects \u2014 recency then severity), a timestamped recent-runs log with independent mention and cited result counts, and a per-project state table. Probe runs are excluded. `generatedAt` is the freshness anchor for every relative timestamp.',
17490
- tags: ["intelligence"],
17491
- parameters: [],
17492
- responses: {
17493
- 200: jsonResponse("Portfolio overview returned.", "PortfolioDto")
17494
- }
17495
- },
17496
17142
  {
17497
17143
  method: "get",
17498
17144
  path: "/api/v1/projects/{name}/overview",
@@ -21888,7 +21534,7 @@ async function googleRoutes(app, opts) {
21888
21534
 
21889
21535
  // ../api-routes/src/ads.ts
21890
21536
  import crypto19 from "crypto";
21891
- import { eq as eq22, and as and15, asc as asc3, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
21537
+ import { eq as eq22, and as and15, asc as asc2, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
21892
21538
  function statusDto(row) {
21893
21539
  if (!row) return { connected: false };
21894
21540
  return {
@@ -22089,7 +21735,7 @@ async function adsRoutes(app, opts) {
22089
21735
  if (entityId) conditions.push(eq22(adsInsightsDaily.entityId, entityId));
22090
21736
  if (from) conditions.push(gte3(adsInsightsDaily.date, from));
22091
21737
  if (to) conditions.push(lte2(adsInsightsDaily.date, to));
22092
- const rows = app.db.select().from(adsInsightsDaily).where(and15(...conditions)).orderBy(asc3(adsInsightsDaily.date)).all();
21738
+ const rows = app.db.select().from(adsInsightsDaily).where(and15(...conditions)).orderBy(asc2(adsInsightsDaily.date)).all();
22093
21739
  const dtoRows = rows.map((row) => ({
22094
21740
  level: row.level,
22095
21741
  entityId: row.entityId,
@@ -25498,7 +25144,7 @@ async function wordpressRoutes(app, opts) {
25498
25144
 
25499
25145
  // ../api-routes/src/backlinks.ts
25500
25146
  import crypto23 from "crypto";
25501
- import { and as and20, asc as asc4, desc as desc14, eq as eq26, sql as sql10 } from "drizzle-orm";
25147
+ import { and as and20, asc as asc3, desc as desc14, eq as eq26, sql as sql10 } from "drizzle-orm";
25502
25148
 
25503
25149
  // ../integration-commoncrawl/src/constants.ts
25504
25150
  import os2 from "os";
@@ -26257,7 +25903,7 @@ async function backlinksRoutes(app, opts) {
26257
25903
  async (request, reply) => {
26258
25904
  const project = resolveProject(app.db, request.params.name);
26259
25905
  const source = parseSourceParam(request.query.source);
26260
- const rows = app.db.select().from(backlinkSummaries).where(and20(eq26(backlinkSummaries.projectId, project.id), eq26(backlinkSummaries.source, source))).orderBy(asc4(backlinkSummaries.queriedAt)).all();
25906
+ const rows = app.db.select().from(backlinkSummaries).where(and20(eq26(backlinkSummaries.projectId, project.id), eq26(backlinkSummaries.source, source))).orderBy(asc3(backlinkSummaries.queriedAt)).all();
26261
25907
  const response = rows.map((r) => ({
26262
25908
  release: r.release,
26263
25909
  totalLinkingDomains: r.totalLinkingDomains,
@@ -34222,7 +33868,7 @@ function dedupeStrings(input) {
34222
33868
 
34223
33869
  // ../api-routes/src/technical-aeo.ts
34224
33870
  import crypto29 from "crypto";
34225
- import { and as and26, asc as asc5, count, desc as desc17, eq as eq36, inArray as inArray13 } from "drizzle-orm";
33871
+ import { and as and26, asc as asc4, count, desc as desc17, eq as eq36, inArray as inArray13 } from "drizzle-orm";
34226
33872
  var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
34227
33873
  function emptyScore(projectName) {
34228
33874
  return {
@@ -34306,7 +33952,7 @@ async function technicalAeoRoutes(app, opts) {
34306
33952
  const total = totalRow?.value ?? 0;
34307
33953
  const limit = parsePositiveInt(request.query.limit, 100, 500);
34308
33954
  const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
34309
- const orderBy = request.query.sort === "score-desc" ? desc17(siteAuditPages.overallScore) : request.query.sort === "url" ? asc5(siteAuditPages.url) : asc5(siteAuditPages.overallScore);
33955
+ const orderBy = request.query.sort === "score-desc" ? desc17(siteAuditPages.overallScore) : request.query.sort === "url" ? asc4(siteAuditPages.url) : asc4(siteAuditPages.overallScore);
34310
33956
  const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
34311
33957
  const pages = rows.map((row) => ({
34312
33958
  url: row.url,
@@ -35241,7 +34887,7 @@ var IntelligenceService = class {
35241
34887
  // Backfill must not replay probe runs as if they were real sweeps.
35242
34888
  ne5(runs.trigger, RunTriggers.probe)
35243
34889
  )
35244
- ).orderBy(asc6(runs.finishedAt)).all();
34890
+ ).orderBy(asc5(runs.finishedAt)).all();
35245
34891
  let startIdx = 0;
35246
34892
  let endIdx = allRuns.length;
35247
34893
  if (opts?.fromRunId) {
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-74SOIAIY.js";
30
+ } from "./chunk-ALJSES3X.js";
31
31
  import {
32
32
  CliError,
33
33
  EXIT_SYSTEM_ERROR,
@@ -44,7 +44,7 @@ import {
44
44
  saveConfig,
45
45
  saveConfigPatch,
46
46
  usageError
47
- } from "./chunk-UVIHWF45.js";
47
+ } from "./chunk-IDI6LMYL.js";
48
48
  import {
49
49
  apiKeys,
50
50
  createClient,
@@ -52,7 +52,7 @@ import {
52
52
  projects,
53
53
  queries,
54
54
  renderReportHtml
55
- } from "./chunk-SNHYRSUF.js";
55
+ } from "./chunk-YBIT5O62.js";
56
56
  import {
57
57
  BacklinkSources,
58
58
  CcReleaseSyncStatuses,
@@ -72,14 +72,13 @@ import {
72
72
  formatIsoDate,
73
73
  formatMicros,
74
74
  formatRatio,
75
- formatRelativeTime,
76
75
  formatRunErrorOneLine,
77
76
  normalizeProjectAliases,
78
77
  notificationEventSchema,
79
78
  providerQuotaPolicySchema,
80
79
  resolveProviderInput,
81
80
  winnabilityClassSchema
82
- } from "./chunk-ADLS64PG.js";
81
+ } from "./chunk-JF7EXHGA.js";
83
82
 
84
83
  // src/cli.ts
85
84
  import { pathToFileURL } from "url";
@@ -9595,103 +9594,6 @@ function pct2(value) {
9595
9594
  return `${(value * 100).toFixed(1)}%`;
9596
9595
  }
9597
9596
 
9598
- // src/commands/portfolio.ts
9599
- async function showPortfolio(opts) {
9600
- const client = createApiClient();
9601
- const portfolio = await client.getPortfolio();
9602
- if (isMachineFormat(opts.format)) {
9603
- if (opts.format === "jsonl") {
9604
- emitJsonl(portfolio.changeFeed);
9605
- return;
9606
- }
9607
- console.log(JSON.stringify(portfolio, null, 2));
9608
- return;
9609
- }
9610
- renderHuman2(portfolio);
9611
- }
9612
- function renderHuman2(p) {
9613
- const now = p.generatedAt;
9614
- const sweep = p.lastSweepAt ? formatRelativeTime(p.lastSweepAt, now) : "never";
9615
- console.log(`
9616
- Portfolio \xB7 ${p.projectCount} project${p.projectCount === 1 ? "" : "s"} \xB7 last sweep ${sweep}
9617
- `);
9618
- const moreLabel = p.changeFeedTotal > p.changeFeed.length ? ` (showing ${p.changeFeed.length} of ${p.changeFeedTotal})` : "";
9619
- console.log(`What changed${moreLabel}:`);
9620
- if (p.changeFeed.length === 0) {
9621
- const empty = p.feedEmptyState;
9622
- console.log(` ${empty ? `${empty.title} \u2014 ${empty.detail}` : "No changes."}`);
9623
- } else {
9624
- for (const c of p.changeFeed) {
9625
- console.log(` ${changeGlyph(c.tone)} ${c.title} (${formatRelativeTime(c.occurredAt, now)})`);
9626
- if (c.detail) console.log(` ${c.detail}`);
9627
- }
9628
- }
9629
- console.log("\nRecent runs (M mentioned in answer \xB7 C cited in sources):");
9630
- if (p.recentRuns.length === 0) {
9631
- console.log(" Run history appears here after the first sweep.");
9632
- } else {
9633
- for (const r of p.recentRuns) {
9634
- console.log(
9635
- ` ${pad(r.projectName, 20)} ${pad(runResult(r), 20)} ${pad(runWhen(r, now), 20)} ${runDuration(r)}`
9636
- );
9637
- }
9638
- }
9639
- console.log("\nProjects:");
9640
- for (const proj of p.projects) {
9641
- const mentioned = `M ${proj.mentionedOfTotal.mentioned}/${proj.mentionedOfTotal.total}`;
9642
- const cited = `C ${proj.citedOfTotal.cited}/${proj.citedOfTotal.total}`;
9643
- console.log(
9644
- ` ${pad(proj.projectSlug, 20)} ${String(proj.mentionScore).padStart(3)} ${pad(mentioned, 10)} ${pad(cited, 10)} ${projectDelta(proj)}`
9645
- );
9646
- }
9647
- console.log();
9648
- }
9649
- function changeGlyph(tone) {
9650
- switch (tone) {
9651
- case "negative":
9652
- return "v";
9653
- case "positive":
9654
- return "^";
9655
- case "caution":
9656
- return "!";
9657
- case "neutral":
9658
- return ".";
9659
- }
9660
- }
9661
- function runResult(r) {
9662
- if (r.status === "failed") return r.errorSummary ?? "failed";
9663
- if (r.mentionedCount == null || r.citedCount == null || r.totalCount == null) return "\u2014";
9664
- return `M ${r.mentionedCount}/${r.totalCount} \xB7 C ${r.citedCount}/${r.totalCount}`;
9665
- }
9666
- function runWhen(r, now) {
9667
- const ts = r.finishedAt ?? r.startedAt ?? r.createdAt;
9668
- const rel = formatRelativeTime(ts, now);
9669
- if (r.status === "running") return `started ${rel}`;
9670
- if (r.status === "queued") return `queued ${rel}`;
9671
- return `finished ${rel}`;
9672
- }
9673
- function runDuration(r) {
9674
- if (r.durationMs == null) {
9675
- return r.status === "running" ? "running" : r.status === "queued" ? "waiting" : "\u2014";
9676
- }
9677
- const seconds = Math.floor(r.durationMs / 1e3);
9678
- if (seconds < 1) return "<1s";
9679
- if (seconds < 60) return `${seconds}s`;
9680
- return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
9681
- }
9682
- function projectDelta(proj) {
9683
- if (!proj.hasEverRun) return "never run";
9684
- const parts = [];
9685
- if (proj.mentionDelta.gained > 0) parts.push(`+${proj.mentionDelta.gained}`);
9686
- if (proj.mentionDelta.lost > 0) parts.push(`-${proj.mentionDelta.lost}`);
9687
- if (parts.length === 0) return proj.mentionDelta.comparable ? "no change" : "first sweep";
9688
- return `${parts.join(" ")} mentioned${proj.mentionDelta.comparable ? "" : "*"}`;
9689
- }
9690
- function pad(value, width) {
9691
- if (value.length >= width) return `${value.slice(0, width - 1)} `;
9692
- return value.padEnd(width);
9693
- }
9694
-
9695
9597
  // src/commands/search.ts
9696
9598
  async function searchProject(project, opts) {
9697
9599
  const client = createApiClient();
@@ -9891,14 +9793,6 @@ var INTELLIGENCE_CLI_COMMANDS = [
9891
9793
  await showOverview(project, { format: input.format, location, since });
9892
9794
  }
9893
9795
  },
9894
- {
9895
- path: ["portfolio"],
9896
- usage: "canonry portfolio [--format json|jsonl]",
9897
- options: {},
9898
- run: async (input) => {
9899
- await showPortfolio({ format: input.format });
9900
- }
9901
- },
9902
9796
  {
9903
9797
  path: ["search"],
9904
9798
  usage: "canonry search <project> <query> [--limit <n>] [--format json]",
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-74SOIAIY.js";
3
+ } from "./chunk-ALJSES3X.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-UVIHWF45.js";
7
- import "./chunk-SNHYRSUF.js";
8
- import "./chunk-ADLS64PG.js";
6
+ } from "./chunk-IDI6LMYL.js";
7
+ import "./chunk-YBIT5O62.js";
8
+ import "./chunk-JF7EXHGA.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-SNHYRSUF.js";
4
- import "./chunk-ADLS64PG.js";
3
+ } from "./chunk-YBIT5O62.js";
4
+ import "./chunk-JF7EXHGA.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };