@canonry/canonry 7.24.1 → 7.25.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 (32) hide show
  1. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +1 -1
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +6 -0
  3. package/assets/agent-workspace/skills/canonry/references/google-business-profile.md +1 -0
  4. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +3 -2
  5. package/assets/assets/{AuditHistoryPanel-DK3zE9dO.js → AuditHistoryPanel-B-9DLSmD.js} +1 -1
  6. package/assets/assets/{BacklinksPage-WYFDcXpX.js → BacklinksPage-DPssWU5-.js} +1 -1
  7. package/assets/assets/{HistoryPage-CSlndAeS.js → HistoryPage-BAPUoHjI.js} +1 -1
  8. package/assets/assets/{MeasurementPropertyPage-CivoZOGQ.js → MeasurementPropertyPage-aTs5l1OV.js} +1 -1
  9. package/assets/assets/{ProjectPage-zidnYv65.js → ProjectPage-sVY1ETmt.js} +1 -1
  10. package/assets/assets/{RunsPage-BGMAZ_mA.js → RunsPage-D0q7ifK3.js} +1 -1
  11. package/assets/assets/{SettingsPage-ndSVVJcE.js → SettingsPage-Oo861eRm.js} +1 -1
  12. package/assets/assets/{SiteHealthSection-C7-RrsKk.js → SiteHealthSection-BMdk3Och.js} +3 -3
  13. package/assets/assets/{TrafficPage-2ANBE9Lc.js → TrafficPage-Ciot_0lN.js} +1 -1
  14. package/assets/assets/{TrafficSourceDetailPage-CLYVB4Uq.js → TrafficSourceDetailPage-D7tWadfJ.js} +1 -1
  15. package/assets/assets/{extract-error-message-BzPoRYiA.js → extract-error-message-Bb4azvlK.js} +1 -1
  16. package/assets/assets/{index-CjowCLs3.js → index-ClA5Nf2V.js} +3 -3
  17. package/assets/assets/{react-sigma_core.esm.min-BmKqjMGN.js → react-sigma_core.esm.min-C-Y9Z74U.js} +1 -1
  18. package/assets/assets/{v2-overview-adapter-C7eI2iBf.js → v2-overview-adapter-D2S25ivE.js} +1 -1
  19. package/assets/index.html +1 -1
  20. package/dist/{chunk-332IBSJJ.js → chunk-6AOIFHC6.js} +1 -1
  21. package/dist/{chunk-5ITYNLS3.js → chunk-BMBHREYM.js} +2 -2
  22. package/dist/{chunk-43FZZFOK.js → chunk-I3546GTK.js} +2 -2
  23. package/dist/{chunk-OAWFZAAJ.js → chunk-NOA7KJDB.js} +3 -3
  24. package/dist/{chunk-35IRQYDW.js → chunk-NX257AKC.js} +145 -25
  25. package/dist/{chunk-656KW4RB.js → chunk-PFEQWGJN.js} +5 -4
  26. package/dist/{chunk-H7UNFLYH.js → chunk-PKQF7BV2.js} +756 -609
  27. package/dist/cli.js +14 -14
  28. package/dist/{demo-server-NLD6B4WH.js → demo-server-RUZWYXSW.js} +4 -4
  29. package/dist/index.js +6 -6
  30. package/dist/{intelligence-service-JFHM2EAY.js → intelligence-service-TYSVXO3S.js} +2 -2
  31. package/dist/mcp.js +4 -4
  32. package/package.json +11 -11
@@ -89,7 +89,7 @@ Shows which source categories AI models cite for your queries. Helps identify:
89
89
  - Content format opportunities (FAQ, how-to, comparison pages)
90
90
 
91
91
  ### Winnability gate + briefs (`canonry content targets|map|brief`)
92
- Every content target carries a deterministic `winnabilityClass`: **ownable** (worth writing for) or **ceded** (the cited surface is dominated by aggregators/OTAs or editorial media, a head term first-party content cannot realistically win). It is derived (no LLM) by classifying each cited domain through the shared surface classifier (own > tracked competitor > stored discovery class > static allow-list), so well-known aggregators/editorial cede immediately, no discovery run required. **`canonry discover run`** improves recall for niche domains the allow-list misses; a target only fails open to `ownable` when none of its cited surface is recognized. `canonry doctor --project <project> --check content.winnability.coverage` reports recognized-coverage of the cited surface and, when the project has no ICP, nudges you to set one (discovery needs it).
92
+ Every content target carries a deterministic `winnabilityClass`: **ownable** (worth writing for) or **ceded** (the cited surface is dominated by aggregators/OTAs or editorial media, a head term first-party content cannot realistically win). It is derived (no LLM) by classifying each cited domain through the shared surface classifier (own > tracked competitor > stored discovery class > static allow-list), so well-known aggregators/editorial cede immediately, no discovery run required. **`canonry discover run`** improves recall for niche domains the allow-list misses; a target only fails open to `ownable` when none of its cited surface is recognized. `canonry doctor --project <project> --check content.winnability.coverage` reports recognized-coverage of the cited surface and, when the project has no ICP, nudges you to set one (discovery needs it). It is advice, not an instrument fault: it shows in `canonry doctor` and never sends a health alert.
93
93
  - `canonry content targets <project> --ownable` — the winnable shortlist (ownable rows sort first by default).
94
94
  - `canonry content map <project>` — the winnability map: which cited surfaces are ceded vs the ranked ownable targets.
95
95
  - `canonry content brief <project> <targetRef>` — synthesize a structured brief (angle, why-winnable, schema hookup) for an **ownable** target. Ceded targets are rejected — don't chase them.
@@ -570,6 +570,8 @@ Available events: `citation.lost`, `citation.gained`, `run.completed`, `run.fail
570
570
 
571
571
  `insight.critical` and `insight.high` fire when the intelligence engine generates critical- or high-severity insights after a sweep completes.
572
572
 
573
+ **Health alerts** (`health.degraded`, `health.recovered`) report on the measurement itself, not on findings, and reach every enabled webhook whether or not it subscribes to them. A doctor pass runs every 6 hours per project. `health.degraded` is sent only when something is new or worse: the project stops being healthy, the worst status rises, or a check starts failing, gets more severe, or reports a different code at the same severity. A pass that finds the same problems, or fewer, sends nothing, so a check clearing, or easing from fail to warn, never produces a second "degraded" alert. An alert that no webhook accepted is sent again on the next pass. `health.recovered` is sent when every check passes again. The payload's `health.failing` lists every failing check; `health.added` lists the codes that are new or worse and `health.cleared` the codes of the checks that stopped failing since the last delivered alert. Discord and Slack cards show them as `New (n)` and `Cleared (n)`, ahead of `Also failing`. Silent advisories (`report.*`, `content.winnability.coverage`, `traffic.source.cache-blindspot`) appear in `cnry doctor` with `notificationPolicy: "silent"` but never page. An optional integration the project does not use is `skipped`, not failed (`gbp.auth.not-connected`, `bing.auth.not-connected`), so it does not page either. Run `cnry doctor --project <project>` to see the current state at any time.
574
+
573
575
  > **No mention events yet.** Notification events cover the citation signal only — there are **no** `mention.lost` / `mention.gained` events today. For mention-first monitoring, read `scores.mentionCoverage` / `scores.mentionShare` via `cnry overview` (or the `insight.*` events, which can be driven by mention-side insights); do not wire automation to mention events that aren't emitted.
574
576
 
575
577
  ## Provider Settings & Quotas
@@ -755,6 +757,8 @@ cnry bing request-indexing <project> --all-unindexed # submit all unindexed
755
757
  cnry bing performance <project> # search performance data
756
758
  ```
757
759
 
760
+ Bing is optional. `cnry doctor --project <project> --check 'bing.*'` reports `bing.auth.connection` as **skipped** (`bing.auth.not-connected`) for a project that never connected Bing, or whose domain's connection was removed with `cnry bing disconnect` (projects on one domain share the connection). It **fails** (`bing.auth.no-connection`) only when the connection is gone while the project still holds Bing data from an earlier connection.
761
+
758
762
  ## WordPress Integration
759
763
 
760
764
  ```bash
@@ -1402,6 +1406,8 @@ cnry backlinks cache prune --release <id> # delete cached release files fro
1402
1406
 
1403
1407
  All commands support `--format json`; collection commands (`list`, `sources`, `releases`) also support `--format jsonl`. A Common Crawl release sync has statuses `queued` → `downloading` → `querying` → `ready` / `failed`. Per-project extracts use the standard run statuses (`queued` → `running` → `completed` / `failed`). Projects with `autoExtractBacklinks` enabled get an extract enqueued automatically when a release sync transitions to `ready`.
1404
1408
 
1409
+ `backlinks sources` reports Common Crawl as `connected` when a release sync has completed and the project has stored Common Crawl data. Syncing the same release again keeps it connected while the download runs. The release sync writes every project's rows, so no project setting is needed. The `backlinks.source.connected` doctor check grades the same rule and warns `backlinks.source.none` otherwise: run `cnry backlinks extract <project>` when a release is currently `ready` but the project has no data yet, or `cnry backlinks sync` when no release is currently ready. Historical completion preserves existing project data through a re-sync but does not make that release available for extraction.
1410
+
1405
1411
  **`jsonl` output schema:** `backlinks list` streams `rows` (each `{ project, release, targetDomain, linkingDomain, numHosts, source }`); `backlinks sources` streams the per-source availability list (`{ project, targetDomain, source, connected, hasData, latestRelease, totalLinkingDomains, lastSyncedAt }`); `backlinks releases` streams cached-release rows bare.
1406
1412
 
1407
1413
  To keep backlinks fresh automatically, schedule a `backlinks-sync` kind (`cnry schedule set <project> --kind backlinks-sync --preset weekly`): each tick re-probes Common Crawl and runs the workspace release sync **only when a newer rolling window is published** (it skips when the newest `ready` sync already covers the latest release, so it never re-downloads a near-identical window).
@@ -191,6 +191,7 @@ canonry doctor --project <name> --check 'gbp.*'
191
191
  ```
192
192
 
193
193
  - `gbp.auth.connection` — OAuth creds present + refresh token works.
194
+ - **Skipped** (`gbp.auth.not-connected`) for a project that never connected GBP: no connection and no selected location. It **fails** (`gbp.auth.no-connection`) only when the connection is gone while the project still has selected locations.
194
195
  - `gbp.auth.scopes` — granted scope includes `business.manage`.
195
196
  - `gbp.account.access` — the tracked account is still listable. A `gbp.account.quota-pending` **warn** means the API access form is still pending Google approval (0 QPM) — auth is fine, the API just isn't enabled yet.
196
197
  - `gbp.places.api-key` — Places API readiness for the listing cross-reference (#648). **Warns** when GBP is connected but no Places key is set, or when no selected location carries a Maps place id (re-run `gbp locations discover`). Skipped when Places is disabled (`places.tier: off`) or GBP isn't connected.
@@ -1052,7 +1052,7 @@ The doctor checks are adapter-agnostic. When they fail or warn:
1052
1052
  | `traffic.source.queue-backlog` | `traffic.queue-backlog.within-drain-budget` | 1–1,000 Queue messages remain. If no new messages arrive, the next scheduled sync can drain them. Run a manual sync to accelerate. |
1053
1053
  | `traffic.source.queue-backlog` | `traffic.queue-backlog.remaining` | More than 1,000 Queue messages remain. Run a manual sync. If the backlog persists, shorten the traffic-sync schedule. |
1054
1054
  | `traffic.source.credentials` | `traffic.credentials.resolve-failed` | Reconnect from the host that owns the source credentials. Queue pull requires a non-empty Account Queues Edit token paired by source ID. |
1055
- | `traffic.source.cache-blindspot` | `traffic.cache-blindspot.wordpress-plugin` | Cache-served requests never execute PHP and produce no event, so a source can look active while real page views go uncounted. Exclude selected AI user agents from every page-cache and CDN layer, or switch to a log/edge source. Warns only, not a failure. |
1055
+ | `traffic.source.cache-blindspot` | `traffic.cache-blindspot.wordpress-plugin` | Cache-served requests never execute PHP and produce no event, so a source can look active while real page views go uncounted. Exclude selected AI user agents from every page-cache and CDN layer, or switch to a log/edge source. Warns only, not a failure. A standing note: it stays for as long as the WordPress source exists, so it is shown by `cnry doctor` but never sends a health alert. |
1056
1056
  | `traffic.source.worker-version` | `traffic.worker-version.waiting-for-first-event` | Send a smoke-test request through the Worker. For Queue delivery, run a sync to ingest it. Then run the doctor again. |
1057
1057
  | `traffic.source.worker-version` | `traffic.worker-version.stale` | Regenerate and redeploy the Worker from the credential-owning host with the source's existing delivery mode, then verify the route or Queue binding. |
1058
1058
 
@@ -1167,4 +1167,5 @@ Cache exclusions for the selected AI agents can recover crawler and user-fetch
1167
1167
  coverage, but they do not recover ordinary browser referrals served from cache.
1168
1168
  Use GA4 for landed browser visits or edge/access logs for cache-independent
1169
1169
  request coverage. The `traffic.source.cache-blindspot` doctor check is a static
1170
- warning; it does not request or impersonate traffic against the public origin.
1170
+ warning; it does not request or impersonate traffic against the public origin,
1171
+ and it never sends a `health.degraded` alert.
@@ -1 +1 @@
1
- import{r as a,u as h,j as e}from"./vendor-tanstack-ZXXkndVj.js";import{dm as L,dn as P,cl as E,y as u,B as x,w as v,T as M}from"./index-CjowCLs3.js";const o=100;function k(s){if(s==="all")return;const n=Number.parseInt(s,10);return new Date(Date.now()-n*24*60*60*1e3).toISOString()}function O(s){const n=s.userAgent?.toLowerCase()??"";return n.includes("canonry-mcp")?"MCP":n.includes("canonry-cli")?"CLI":n.includes("mozilla/")?"Dashboard":s.actor==="scheduler"?"Scheduler":s.actor==="agent"?"Agent":s.actor==="mcp"?"MCP":s.actor==="cli"?"CLI":s.actor}function B(s){return/delete|remove|revoke|disconnect|failed|refused/.test(s)?"negative":/create|add|connect|completed/.test(s)?"positive":/update|replace|sync|apply/.test(s)?"caution":"neutral"}function D(s){return[s.action,s.actor,s.entityType,s.entityId,s.actorSession,s.userAgent,s.diff==null?"":JSON.stringify(s.diff)].filter(Boolean).join(" ").toLowerCase()}function H({projectName:s}){const[n,l]=a.useState(0),[c,y]=a.useState("90d"),[m,N]=a.useState(""),[p,w]=a.useState(""),S=a.useMemo(()=>k(c),[c]),g={limit:o,offset:n*o,since:S,actor:m||void 0},C=h({...L({client:u,path:{name:s??""},query:g}),enabled:!!s}),A=h({...P({client:u,query:g}),enabled:!s}),f=h({...E({client:u}),enabled:!s}),i=s?C:A,r=i.data??[],I=a.useMemo(()=>new Map((f.data??[]).map(t=>[t.id,t.displayName||t.name])),[f.data]),d=p.trim().toLowerCase(),j=a.useMemo(()=>d?r.filter(t=>D(t).includes(d)):r,[r,d]),b=t=>{l(0),t()};return i.isLoading?e.jsx("p",{className:"supporting-copy mt-6",role:"status",children:"Loading change history…"}):e.jsxs("section",{className:"mt-6","aria-labelledby":"change-history-heading",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Audit trail"}),e.jsx("h2",{id:"change-history-heading",children:"Change history"}),e.jsx("p",{className:"supporting-copy mt-1 max-w-2xl",children:"Configuration and operator actions. Execution outcomes remain in Runs."})]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",onClick:()=>{i.refetch()},disabled:i.isFetching,children:i.isFetching?"Refreshing…":"Refresh"})]}),e.jsxs("div",{className:"mt-4 grid gap-2 sm:grid-cols-3",children:[e.jsx("input",{type:"search","aria-label":"Search change history",value:p,onChange:t=>w(t.target.value),placeholder:"Search actions, entities, or details",className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong placeholder-mono-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600"}),e.jsxs("select",{"aria-label":"Filter change history by actor",value:m,onChange:t=>b(()=>N(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"",children:"All actors"}),e.jsx("option",{value:"api",children:"API and dashboard"}),e.jsx("option",{value:"cli",children:"CLI"}),e.jsx("option",{value:"scheduler",children:"Scheduler"}),e.jsx("option",{value:"agent",children:"Agent"}),e.jsx("option",{value:"mcp",children:"MCP"})]}),e.jsxs("select",{"aria-label":"Filter change history by date range",value:c,onChange:t=>b(()=>y(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"30d",children:"Last 30 days"}),e.jsx("option",{value:"90d",children:"Last 90 days"}),e.jsx("option",{value:"365d",children:"Last year"}),e.jsx("option",{value:"all",children:"All retained history"})]})]}),i.isError?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"Change history unavailable"}),e.jsx("p",{children:i.error instanceof Error?i.error.message:"Could not load the audit trail."})]}):j.length===0?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"No changes match these filters"}),e.jsx("p",{children:"Widen the date range or clear the actor and search filters."})]}):e.jsx("div",{className:"evidence-table-wrap mt-4",children:e.jsxs("table",{className:"evidence-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"When"}),s?null:e.jsx("th",{children:"Scope"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Entity"}),e.jsx("th",{children:"Origin"}),e.jsx("th",{children:"Details"})]})}),e.jsx("tbody",{children:j.map(t=>e.jsxs("tr",{children:[e.jsx("td",{className:"whitespace-nowrap tabular-nums text-muted",children:new Date(t.createdAt).toLocaleString()}),s?null:e.jsx("td",{className:"text-secondary",children:t.projectId?I.get(t.projectId)??`Deleted project · ${t.projectId}`:"Instance settings"}),e.jsx("td",{children:e.jsx(M,{tone:B(t.action),children:t.action})}),e.jsxs("td",{children:[e.jsx("span",{className:"text-strong",children:t.entityType}),t.entityId?e.jsx("span",{className:"mt-0.5 block max-w-48 truncate font-mono text-[11px] text-faint",title:t.entityId,children:t.entityId}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"text-secondary",children:O(t)}),t.actorSession?e.jsxs("span",{className:"mt-0.5 block max-w-40 truncate font-mono text-[11px] text-faint",title:t.actorSession,children:["Session ",t.actorSession]}):null]}),e.jsx("td",{children:t.diff==null?e.jsx("span",{className:"text-faint",children:"No field diff"}):e.jsxs("details",{children:[e.jsx("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary hover:text-strong",children:"View diff"}),e.jsx("pre",{className:"max-h-72 max-w-xl overflow-auto whitespace-pre-wrap break-words rounded-md bg-bg-elevated p-3 text-xs text-secondary",children:JSON.stringify(t.diff,null,2)})]})})]},t.id))})]})}),!i.isError&&(n>0||r.length===o)?e.jsxs("div",{className:"mt-4 flex items-center justify-between gap-3",children:[e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:n===0,onClick:()=>l(t=>Math.max(0,t-1)),children:"Previous"}),e.jsxs("span",{className:"text-xs tabular-nums text-muted",children:["Page ",n+1]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:r.length<o,onClick:()=>l(t=>t+1),children:"Next"})]}):null]})}export{H as A};
1
+ import{r as a,u as h,j as e}from"./vendor-tanstack-ZXXkndVj.js";import{dm as L,dn as P,cl as E,y as u,B as x,w as v,T as M}from"./index-ClA5Nf2V.js";const o=100;function k(s){if(s==="all")return;const n=Number.parseInt(s,10);return new Date(Date.now()-n*24*60*60*1e3).toISOString()}function O(s){const n=s.userAgent?.toLowerCase()??"";return n.includes("canonry-mcp")?"MCP":n.includes("canonry-cli")?"CLI":n.includes("mozilla/")?"Dashboard":s.actor==="scheduler"?"Scheduler":s.actor==="agent"?"Agent":s.actor==="mcp"?"MCP":s.actor==="cli"?"CLI":s.actor}function B(s){return/delete|remove|revoke|disconnect|failed|refused/.test(s)?"negative":/create|add|connect|completed/.test(s)?"positive":/update|replace|sync|apply/.test(s)?"caution":"neutral"}function D(s){return[s.action,s.actor,s.entityType,s.entityId,s.actorSession,s.userAgent,s.diff==null?"":JSON.stringify(s.diff)].filter(Boolean).join(" ").toLowerCase()}function H({projectName:s}){const[n,l]=a.useState(0),[c,y]=a.useState("90d"),[m,N]=a.useState(""),[p,w]=a.useState(""),S=a.useMemo(()=>k(c),[c]),g={limit:o,offset:n*o,since:S,actor:m||void 0},C=h({...L({client:u,path:{name:s??""},query:g}),enabled:!!s}),A=h({...P({client:u,query:g}),enabled:!s}),f=h({...E({client:u}),enabled:!s}),i=s?C:A,r=i.data??[],I=a.useMemo(()=>new Map((f.data??[]).map(t=>[t.id,t.displayName||t.name])),[f.data]),d=p.trim().toLowerCase(),j=a.useMemo(()=>d?r.filter(t=>D(t).includes(d)):r,[r,d]),b=t=>{l(0),t()};return i.isLoading?e.jsx("p",{className:"supporting-copy mt-6",role:"status",children:"Loading change history…"}):e.jsxs("section",{className:"mt-6","aria-labelledby":"change-history-heading",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Audit trail"}),e.jsx("h2",{id:"change-history-heading",children:"Change history"}),e.jsx("p",{className:"supporting-copy mt-1 max-w-2xl",children:"Configuration and operator actions. Execution outcomes remain in Runs."})]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",onClick:()=>{i.refetch()},disabled:i.isFetching,children:i.isFetching?"Refreshing…":"Refresh"})]}),e.jsxs("div",{className:"mt-4 grid gap-2 sm:grid-cols-3",children:[e.jsx("input",{type:"search","aria-label":"Search change history",value:p,onChange:t=>w(t.target.value),placeholder:"Search actions, entities, or details",className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong placeholder-mono-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600"}),e.jsxs("select",{"aria-label":"Filter change history by actor",value:m,onChange:t=>b(()=>N(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"",children:"All actors"}),e.jsx("option",{value:"api",children:"API and dashboard"}),e.jsx("option",{value:"cli",children:"CLI"}),e.jsx("option",{value:"scheduler",children:"Scheduler"}),e.jsx("option",{value:"agent",children:"Agent"}),e.jsx("option",{value:"mcp",children:"MCP"})]}),e.jsxs("select",{"aria-label":"Filter change history by date range",value:c,onChange:t=>b(()=>y(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"30d",children:"Last 30 days"}),e.jsx("option",{value:"90d",children:"Last 90 days"}),e.jsx("option",{value:"365d",children:"Last year"}),e.jsx("option",{value:"all",children:"All retained history"})]})]}),i.isError?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"Change history unavailable"}),e.jsx("p",{children:i.error instanceof Error?i.error.message:"Could not load the audit trail."})]}):j.length===0?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"No changes match these filters"}),e.jsx("p",{children:"Widen the date range or clear the actor and search filters."})]}):e.jsx("div",{className:"evidence-table-wrap mt-4",children:e.jsxs("table",{className:"evidence-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"When"}),s?null:e.jsx("th",{children:"Scope"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Entity"}),e.jsx("th",{children:"Origin"}),e.jsx("th",{children:"Details"})]})}),e.jsx("tbody",{children:j.map(t=>e.jsxs("tr",{children:[e.jsx("td",{className:"whitespace-nowrap tabular-nums text-muted",children:new Date(t.createdAt).toLocaleString()}),s?null:e.jsx("td",{className:"text-secondary",children:t.projectId?I.get(t.projectId)??`Deleted project · ${t.projectId}`:"Instance settings"}),e.jsx("td",{children:e.jsx(M,{tone:B(t.action),children:t.action})}),e.jsxs("td",{children:[e.jsx("span",{className:"text-strong",children:t.entityType}),t.entityId?e.jsx("span",{className:"mt-0.5 block max-w-48 truncate font-mono text-[11px] text-faint",title:t.entityId,children:t.entityId}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"text-secondary",children:O(t)}),t.actorSession?e.jsxs("span",{className:"mt-0.5 block max-w-40 truncate font-mono text-[11px] text-faint",title:t.actorSession,children:["Session ",t.actorSession]}):null]}),e.jsx("td",{children:t.diff==null?e.jsx("span",{className:"text-faint",children:"No field diff"}):e.jsxs("details",{children:[e.jsx("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary hover:text-strong",children:"View diff"}),e.jsx("pre",{className:"max-h-72 max-w-xl overflow-auto whitespace-pre-wrap break-words rounded-md bg-bg-elevated p-3 text-xs text-secondary",children:JSON.stringify(t.diff,null,2)})]})})]},t.id))})]})}),!i.isError&&(n>0||r.length===o)?e.jsxs("div",{className:"mt-4 flex items-center justify-between gap-3",children:[e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:n===0,onClick:()=>l(t=>Math.max(0,t-1)),children:"Previous"}),e.jsxs("span",{className:"text-xs tabular-nums text-muted",children:["Page ",n+1]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:r.length<o,onClick:()=>l(t=>t+1),children:"Next"})]}):null]})}export{H as A};
@@ -1 +1 @@
1
- import{r as n,j as e}from"./vendor-tanstack-ZXXkndVj.js";import{dC as _,aG as O,dD as U,dE as J,dF as K,w as i,T as u,z as d,B as k,E as F,dG as V,dH as Y,aJ as X,dI as Z}from"./index-CjowCLs3.js";import{H as p}from"./Hint-DICI5Jq9.js";import{I as ee,T as se,E as te,j as ae,N as ne}from"./vendor-lucide-Y6jANGfG.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";const re="https://commoncrawl.org/web-graphs";function w(t){return t==null?"—":t>=1e12?`${(t/1e12).toFixed(1)} TB`:t>=1e9?`${(t/1e9).toFixed(1)} GB`:t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${(t/1e3).toFixed(1)} KB`:`${t} B`}function j(t){if(!t)return"—";const f=Date.now()-new Date(t).getTime(),a=Math.floor(f/6e4);if(a<1)return"just now";if(a<60)return`${a}m ago`;const o=Math.floor(a/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function S(t){switch(t){case"ready":return"positive";case"failed":return"negative";case"downloading":case"querying":case"queued":return"caution"}}function ue(){const[t,f]=n.useState(null),[a,o]=n.useState(null),[y,P]=n.useState([]),[g,L]=n.useState([]),[x,T]=n.useState(null),[C,B]=n.useState(!0),[D,R]=n.useState(!1),[h,E]=n.useState(!1),[N,b]=n.useState(""),[$,v]=n.useState(!1),[I,l]=n.useState(null),[A,c]=n.useState(null),m=n.useCallback(async()=>{B(!0),l(null);try{const[s,r,z,Q,W]=await Promise.all([_(),O().catch(()=>null),U().catch(()=>[]),J().catch(()=>[]),K().catch(()=>null)]);f(s),o(r),P(z),L(Q),T(W)}catch(s){l(s instanceof Error?s.message:"Failed to load backlinks status")}finally{B(!1)}},[]);n.useEffect(()=>{m()},[m]);async function q(){R(!0),l(null),c(null);try{const s=await V();c(s.alreadyPresent?`DuckDB already installed (${s.version}).`:`Installed DuckDB ${s.version}.`),await m()}catch(s){l(s instanceof Error?s.message:"Failed to install DuckDB")}finally{R(!1)}}async function M(){const s=N.trim()||void 0;E(!0),l(null),c(null);try{const r=await Y(s);c(s?`Queued sync for ${r.release}. Download + query runs in the background.`:`Queued sync for auto-discovered release ${r.release}. Download + query runs in the background.`),b(""),v(!1),await m()}catch(r){r instanceof X&&r.code==="MISSING_DEPENDENCY"?l("DuckDB is not installed. Install it first."):l(r instanceof Error?r.message:"Failed to trigger sync")}finally{E(!1)}}async function G(s){l(null),c(null);try{await Z(s),c(`Pruned cached release ${s}.`),await m()}catch(r){l(r instanceof Error?r.message:"Failed to prune release")}}const H=a?.status==="ready"&&g.every(s=>s.release!==a.release);return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Backlink data"}),e.jsx("p",{className:"page-subtitle",children:"Manage the shared backlink source and review its latest data."})]})}),I&&e.jsx(i,{className:"surface-card p-4 mb-4 border-negative-800/60",children:e.jsx("p",{className:"text-sm text-negative",children:I})}),A&&e.jsx(i,{className:"surface-card p-4 mb-4 border-positive-800/60",children:e.jsx("p",{className:"text-sm text-positive",children:A})}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Readiness"}),e.jsx("h2",{children:"Backlink source"})]}),t?.duckdbInstalled?e.jsx(u,{tone:"positive",children:"Installed"}):e.jsx(u,{tone:"caution",children:"Not installed"})]}),e.jsx(i,{className:"surface-card p-4",children:C?e.jsx("p",{className:"text-sm text-muted",children:"Checking…"}):t?.duckdbInstalled?e.jsx("p",{className:"text-sm text-secondary",children:"Ready to sync a Common Crawl release."}):e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-sm text-secondary",children:"Install the local query engine to enable release syncs."}),!d()&&e.jsxs(k,{type:"button",size:"sm",disabled:D,onClick:F(q),children:[e.jsx(ee,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),D?"Installing…":"Install DuckDB"]})]})})]}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Latest sync"}),e.jsxs("h2",{className:"flex items-center gap-2",children:["Release sync",e.jsx(p,{label:"What is a release sync?",children:"A release sync downloads one Common Crawl dump (~16 GB) and extracts backlinks for every project in this workspace in one pass. This is the heavy job — subsequent per-project re-runs skip the download and just re-query the cached files."})]})]}),a&&e.jsx(u,{tone:S(a.status),children:a.status})]}),e.jsxs(i,{className:"surface-card p-5",children:[a?e.jsxs("div",{className:"space-y-2 text-sm",children:[e.jsxs("p",{className:"text-strong",children:["Release ",e.jsx("code",{className:"text-neutral",children:a.release})]}),a.phaseDetail&&e.jsx("p",{className:"text-secondary",children:a.phaseDetail}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs text-muted pt-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Projects"}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.projectsProcessed??"—"})]}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-faint uppercase tracking-wide flex items-center gap-1",children:["Rows",e.jsx(p,{label:"What are rows?",children:"Total number of (project, referring domain) pairs persisted in SQLite from this sync, across every project in the workspace."})]}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.domainsDiscovered??"—"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Started"}),e.jsx("p",{className:"text-neutral mt-0.5",children:j(a.downloadStartedAt??a.createdAt)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Finished"}),e.jsx("p",{className:"text-neutral mt-0.5",children:j(a.queryFinishedAt)})]})]}),a.error&&e.jsx("p",{className:"text-sm text-negative-400 pt-2",children:a.error})]}):e.jsx("p",{className:"text-sm text-muted",children:"No release sync has run in this workspace yet."}),H&&e.jsx("div",{className:"mt-4 rounded border border-caution-800/60 bg-caution-950/20 p-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(se,{className:"h-4 w-4 text-caution-400 shrink-0 mt-0.5","aria-hidden":!0}),e.jsxs("div",{className:"text-sm text-neutral leading-relaxed",children:[e.jsx("p",{className:"font-medium text-caution-200",children:"Cached files for this release are missing."}),e.jsx("p",{className:"mt-1 text-secondary",children:"Sync this release again, or sync the newest release, before refreshing individual projects."})]})]})}),e.jsxs("div",{className:"mt-4 rounded border border-base bg-bg-elevated/40 p-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wide text-muted",children:"Auto-detected release"}),x?e.jsxs("p",{className:"text-sm text-strong mt-0.5",children:[e.jsx("code",{className:"text-heading",children:x.release}),e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["Vertex ",w(x.vertexBytes),", edges ",w(x.edgesBytes)]})]}):e.jsx("p",{className:"text-sm text-muted mt-0.5",children:C?"Checking Common Crawl…":"Could not find a release. Choose one below."}),e.jsxs("a",{href:re,target:"_blank",rel:"noopener noreferrer",className:"mt-1 inline-flex items-center gap-1 text-xs text-secondary hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:["Browse all Common Crawl web-graph releases",e.jsx(te,{className:"h-3 w-3","aria-hidden":!0})]})]}),!d()&&e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsxs(k,{type:"button",size:"sm",disabled:h||!t?.duckdbInstalled||!x&&!N.trim(),onClick:F(M),children:[e.jsx(ae,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),h?"Queuing…":"Run sync"]}),e.jsxs(p,{label:"What does Run sync do?",children:[e.jsxs("span",{className:"block",children:["Downloads the auto-detected (or chosen) Common Crawl release (~16 GB) to"," ",e.jsx("code",{className:"text-neutral",children:"~/.canonry/cache/commoncrawl/"}),", then runs a single DuckDB query that extracts referring domains for every project in this workspace."]}),e.jsxs("span",{className:"mt-2 block text-secondary",children:["First time for a release: ",e.jsx("span",{className:"text-strong",children:"~10–20 min download + ~5 min query"}),". Re-running the same release later: ",e.jsx("span",{className:"text-strong",children:"skips download, just re-queries"})," (~5 min)."]})]})]})]}),d()?null:$?e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("input",{type:"text",className:"flex-1 min-w-[240px] rounded border border-strong bg-transparent px-2.5 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none",placeholder:"cc-main-2026-jan-feb-mar",value:N,onChange:s=>b(s.target.value),disabled:h,autoFocus:!0}),e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>{b(""),v(!1)},disabled:h,children:"Cancel"})]}):e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>v(!0),disabled:h,children:"Use a different release →"})]}),!t?.duckdbInstalled&&e.jsx("p",{className:"text-sm text-secondary mt-2",children:"Install DuckDB first to enable sync."})]})]}),e.jsxs("details",{className:"page-section-divider group",children:[e.jsx("summary",{className:"cursor-pointer text-sm font-medium text-secondary hover:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:"Technical details and cache"}),e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-secondary mb-3",children:"Cached releases support project re-extracts. Pruning a release does not remove saved backlink results."}),e.jsx(i,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Sync status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Size"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Last used"}),!d()&&e.jsx("th",{className:"px-4 py-2 font-medium sr-only",children:"Actions"})]})}),e.jsxs("tbody",{children:[g.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:s.syncStatus?e.jsx(u,{tone:S(s.syncStatus),children:s.syncStatus}):e.jsx("span",{className:"text-faint",children:"—"})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:w(s.bytes)}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:j(s.lastUsedAt)}),!d()&&e.jsx("td",{className:"px-4 py-2 text-right",children:e.jsxs("div",{className:"inline-flex items-center gap-1",children:[e.jsxs(k,{type:"button",variant:"outline",size:"sm",onClick:()=>{G(s.release)},children:[e.jsx(ne,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),"Prune"]}),e.jsx(p,{label:"What does Prune do?",placement:"top",children:"Deletes the ~16 GB cache for this release from disk. Backlink results already in SQLite remain untouched. To re-run extracts against this release, you’d have to sync it again (another ~16 GB download)."})]})})]},s.release)),g.length===0&&e.jsx("tr",{children:e.jsx("td",{className:"px-4 py-4 text-sm text-muted",colSpan:d()?4:5,children:"No cached releases on this machine. If you ran a sync from a different machine (or deleted the cache), the backlink data is still in the database — but you’ll need to re-sync a release to run new extracts."})})]})]})}),e.jsx("p",{className:"mt-3 text-xs text-muted",children:"Common Crawl files are stored locally. DuckDB reads them; Canonry stores results in its normal database."})]})]}),y.length>1&&e.jsxs("section",{className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"History"}),e.jsx("h2",{children:"Past release syncs"})]})}),e.jsx(i,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Projects"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Rows"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Finished"})]})}),e.jsx("tbody",{children:y.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:e.jsx(u,{tone:S(s.status),children:s.status})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.projectsProcessed??"—"}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.domainsDiscovered??"—"}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:j(s.queryFinishedAt??s.updatedAt)})]},s.id))})]})})]})]})}export{ue as BacklinksPage};
1
+ import{r as n,j as e}from"./vendor-tanstack-ZXXkndVj.js";import{dC as _,aG as O,dD as U,dE as J,dF as K,w as i,T as u,z as d,B as k,E as F,dG as V,dH as Y,aJ as X,dI as Z}from"./index-ClA5Nf2V.js";import{H as p}from"./Hint-DICI5Jq9.js";import{I as ee,T as se,E as te,j as ae,N as ne}from"./vendor-lucide-Y6jANGfG.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";const re="https://commoncrawl.org/web-graphs";function w(t){return t==null?"—":t>=1e12?`${(t/1e12).toFixed(1)} TB`:t>=1e9?`${(t/1e9).toFixed(1)} GB`:t>=1e6?`${(t/1e6).toFixed(1)} MB`:t>=1e3?`${(t/1e3).toFixed(1)} KB`:`${t} B`}function j(t){if(!t)return"—";const f=Date.now()-new Date(t).getTime(),a=Math.floor(f/6e4);if(a<1)return"just now";if(a<60)return`${a}m ago`;const o=Math.floor(a/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function S(t){switch(t){case"ready":return"positive";case"failed":return"negative";case"downloading":case"querying":case"queued":return"caution"}}function ue(){const[t,f]=n.useState(null),[a,o]=n.useState(null),[y,P]=n.useState([]),[g,L]=n.useState([]),[x,T]=n.useState(null),[C,B]=n.useState(!0),[D,R]=n.useState(!1),[h,E]=n.useState(!1),[N,b]=n.useState(""),[$,v]=n.useState(!1),[I,l]=n.useState(null),[A,c]=n.useState(null),m=n.useCallback(async()=>{B(!0),l(null);try{const[s,r,z,Q,W]=await Promise.all([_(),O().catch(()=>null),U().catch(()=>[]),J().catch(()=>[]),K().catch(()=>null)]);f(s),o(r),P(z),L(Q),T(W)}catch(s){l(s instanceof Error?s.message:"Failed to load backlinks status")}finally{B(!1)}},[]);n.useEffect(()=>{m()},[m]);async function q(){R(!0),l(null),c(null);try{const s=await V();c(s.alreadyPresent?`DuckDB already installed (${s.version}).`:`Installed DuckDB ${s.version}.`),await m()}catch(s){l(s instanceof Error?s.message:"Failed to install DuckDB")}finally{R(!1)}}async function M(){const s=N.trim()||void 0;E(!0),l(null),c(null);try{const r=await Y(s);c(s?`Queued sync for ${r.release}. Download + query runs in the background.`:`Queued sync for auto-discovered release ${r.release}. Download + query runs in the background.`),b(""),v(!1),await m()}catch(r){r instanceof X&&r.code==="MISSING_DEPENDENCY"?l("DuckDB is not installed. Install it first."):l(r instanceof Error?r.message:"Failed to trigger sync")}finally{E(!1)}}async function G(s){l(null),c(null);try{await Z(s),c(`Pruned cached release ${s}.`),await m()}catch(r){l(r instanceof Error?r.message:"Failed to prune release")}}const H=a?.status==="ready"&&g.every(s=>s.release!==a.release);return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"Backlink data"}),e.jsx("p",{className:"page-subtitle",children:"Manage the shared backlink source and review its latest data."})]})}),I&&e.jsx(i,{className:"surface-card p-4 mb-4 border-negative-800/60",children:e.jsx("p",{className:"text-sm text-negative",children:I})}),A&&e.jsx(i,{className:"surface-card p-4 mb-4 border-positive-800/60",children:e.jsx("p",{className:"text-sm text-positive",children:A})}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Readiness"}),e.jsx("h2",{children:"Backlink source"})]}),t?.duckdbInstalled?e.jsx(u,{tone:"positive",children:"Installed"}):e.jsx(u,{tone:"caution",children:"Not installed"})]}),e.jsx(i,{className:"surface-card p-4",children:C?e.jsx("p",{className:"text-sm text-muted",children:"Checking…"}):t?.duckdbInstalled?e.jsx("p",{className:"text-sm text-secondary",children:"Ready to sync a Common Crawl release."}):e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-sm text-secondary",children:"Install the local query engine to enable release syncs."}),!d()&&e.jsxs(k,{type:"button",size:"sm",disabled:D,onClick:F(q),children:[e.jsx(ee,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),D?"Installing…":"Install DuckDB"]})]})})]}),e.jsxs("section",{className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Latest sync"}),e.jsxs("h2",{className:"flex items-center gap-2",children:["Release sync",e.jsx(p,{label:"What is a release sync?",children:"A release sync downloads one Common Crawl dump (~16 GB) and extracts backlinks for every project in this workspace in one pass. This is the heavy job — subsequent per-project re-runs skip the download and just re-query the cached files."})]})]}),a&&e.jsx(u,{tone:S(a.status),children:a.status})]}),e.jsxs(i,{className:"surface-card p-5",children:[a?e.jsxs("div",{className:"space-y-2 text-sm",children:[e.jsxs("p",{className:"text-strong",children:["Release ",e.jsx("code",{className:"text-neutral",children:a.release})]}),a.phaseDetail&&e.jsx("p",{className:"text-secondary",children:a.phaseDetail}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs text-muted pt-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Projects"}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.projectsProcessed??"—"})]}),e.jsxs("div",{children:[e.jsxs("p",{className:"text-faint uppercase tracking-wide flex items-center gap-1",children:["Rows",e.jsx(p,{label:"What are rows?",children:"Total number of (project, referring domain) pairs persisted in SQLite from this sync, across every project in the workspace."})]}),e.jsx("p",{className:"text-neutral mt-0.5",children:a.domainsDiscovered??"—"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Started"}),e.jsx("p",{className:"text-neutral mt-0.5",children:j(a.downloadStartedAt??a.createdAt)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-faint uppercase tracking-wide",children:"Finished"}),e.jsx("p",{className:"text-neutral mt-0.5",children:j(a.queryFinishedAt)})]})]}),a.error&&e.jsx("p",{className:"text-sm text-negative-400 pt-2",children:a.error})]}):e.jsx("p",{className:"text-sm text-muted",children:"No release sync has run in this workspace yet."}),H&&e.jsx("div",{className:"mt-4 rounded border border-caution-800/60 bg-caution-950/20 p-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(se,{className:"h-4 w-4 text-caution-400 shrink-0 mt-0.5","aria-hidden":!0}),e.jsxs("div",{className:"text-sm text-neutral leading-relaxed",children:[e.jsx("p",{className:"font-medium text-caution-200",children:"Cached files for this release are missing."}),e.jsx("p",{className:"mt-1 text-secondary",children:"Sync this release again, or sync the newest release, before refreshing individual projects."})]})]})}),e.jsxs("div",{className:"mt-4 rounded border border-base bg-bg-elevated/40 p-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3 mb-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] uppercase tracking-wide text-muted",children:"Auto-detected release"}),x?e.jsxs("p",{className:"text-sm text-strong mt-0.5",children:[e.jsx("code",{className:"text-heading",children:x.release}),e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["Vertex ",w(x.vertexBytes),", edges ",w(x.edgesBytes)]})]}):e.jsx("p",{className:"text-sm text-muted mt-0.5",children:C?"Checking Common Crawl…":"Could not find a release. Choose one below."}),e.jsxs("a",{href:re,target:"_blank",rel:"noopener noreferrer",className:"mt-1 inline-flex items-center gap-1 text-xs text-secondary hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:["Browse all Common Crawl web-graph releases",e.jsx(te,{className:"h-3 w-3","aria-hidden":!0})]})]}),!d()&&e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsxs(k,{type:"button",size:"sm",disabled:h||!t?.duckdbInstalled||!x&&!N.trim(),onClick:F(M),children:[e.jsx(ae,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),h?"Queuing…":"Run sync"]}),e.jsxs(p,{label:"What does Run sync do?",children:[e.jsxs("span",{className:"block",children:["Downloads the auto-detected (or chosen) Common Crawl release (~16 GB) to"," ",e.jsx("code",{className:"text-neutral",children:"~/.canonry/cache/commoncrawl/"}),", then runs a single DuckDB query that extracts referring domains for every project in this workspace."]}),e.jsxs("span",{className:"mt-2 block text-secondary",children:["First time for a release: ",e.jsx("span",{className:"text-strong",children:"~10–20 min download + ~5 min query"}),". Re-running the same release later: ",e.jsx("span",{className:"text-strong",children:"skips download, just re-queries"})," (~5 min)."]})]})]})]}),d()?null:$?e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("input",{type:"text",className:"flex-1 min-w-[240px] rounded border border-strong bg-transparent px-2.5 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none",placeholder:"cc-main-2026-jan-feb-mar",value:N,onChange:s=>b(s.target.value),disabled:h,autoFocus:!0}),e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>{b(""),v(!1)},disabled:h,children:"Cancel"})]}):e.jsx("button",{type:"button",className:"text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",onClick:()=>v(!0),disabled:h,children:"Use a different release →"})]}),!t?.duckdbInstalled&&e.jsx("p",{className:"text-sm text-secondary mt-2",children:"Install DuckDB first to enable sync."})]})]}),e.jsxs("details",{className:"page-section-divider group",children:[e.jsx("summary",{className:"cursor-pointer text-sm font-medium text-secondary hover:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded",children:"Technical details and cache"}),e.jsxs("div",{className:"mt-4",children:[e.jsx("p",{className:"text-sm text-secondary mb-3",children:"Cached releases support project re-extracts. Pruning a release does not remove saved backlink results."}),e.jsx(i,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Sync status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Size"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Last used"}),!d()&&e.jsx("th",{className:"px-4 py-2 font-medium sr-only",children:"Actions"})]})}),e.jsxs("tbody",{children:[g.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:s.syncStatus?e.jsx(u,{tone:S(s.syncStatus),children:s.syncStatus}):e.jsx("span",{className:"text-faint",children:"—"})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:w(s.bytes)}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:j(s.lastUsedAt)}),!d()&&e.jsx("td",{className:"px-4 py-2 text-right",children:e.jsxs("div",{className:"inline-flex items-center gap-1",children:[e.jsxs(k,{type:"button",variant:"outline",size:"sm",onClick:()=>{G(s.release)},children:[e.jsx(ne,{className:"h-4 w-4 mr-1.5","aria-hidden":!0}),"Prune"]}),e.jsx(p,{label:"What does Prune do?",placement:"top",children:"Deletes the ~16 GB cache for this release from disk. Backlink results already in SQLite remain untouched. To re-run extracts against this release, you’d have to sync it again (another ~16 GB download)."})]})})]},s.release)),g.length===0&&e.jsx("tr",{children:e.jsx("td",{className:"px-4 py-4 text-sm text-muted",colSpan:d()?4:5,children:"No cached releases on this machine. If you ran a sync from a different machine (or deleted the cache), the backlink data is still in the database — but you’ll need to re-sync a release to run new extracts."})})]})]})}),e.jsx("p",{className:"mt-3 text-xs text-muted",children:"Common Crawl files are stored locally. DuckDB reads them; Canonry stores results in its normal database."})]})]}),y.length>1&&e.jsxs("section",{className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"History"}),e.jsx("h2",{children:"Past release syncs"})]})}),e.jsx(i,{className:"surface-card overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-base text-left text-xs uppercase tracking-wide text-faint",children:[e.jsx("th",{className:"px-4 py-2 font-medium",children:"Release"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Status"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Projects"}),e.jsx("th",{className:"px-4 py-2 text-right font-medium",children:"Rows"}),e.jsx("th",{className:"px-4 py-2 font-medium",children:"Finished"})]})}),e.jsx("tbody",{children:y.map(s=>e.jsxs("tr",{className:"border-b border-mono-900 last:border-0",children:[e.jsx("td",{className:"px-4 py-2 text-strong",children:e.jsx("code",{children:s.release})}),e.jsx("td",{className:"px-4 py-2",children:e.jsx(u,{tone:S(s.status),children:s.status})}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.projectsProcessed??"—"}),e.jsx("td",{className:"px-4 py-2 text-right text-secondary tabular-nums",children:s.domainsDiscovered??"—"}),e.jsx("td",{className:"px-4 py-2 text-secondary",children:j(s.queryFinishedAt??s.updatedAt)})]},s.id))})]})})]})]})}export{ue as BacklinksPage};
@@ -1 +1 @@
1
- import{j as e}from"./vendor-tanstack-ZXXkndVj.js";import{A as s}from"./AuditHistoryPanel-DK3zE9dO.js";import"./index-CjowCLs3.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-lucide-Y6jANGfG.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";function l(){return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"History"}),e.jsx("p",{className:"page-subtitle",children:"Changes to projects and settings."})]})}),e.jsx(s,{})]})}export{l as HistoryPage};
1
+ import{j as e}from"./vendor-tanstack-ZXXkndVj.js";import{A as s}from"./AuditHistoryPanel-B-9DLSmD.js";import"./index-ClA5Nf2V.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-lucide-Y6jANGfG.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";function l(){return e.jsxs("div",{className:"page-container",children:[e.jsx("div",{className:"page-header",children:e.jsxs("div",{className:"page-header-left",children:[e.jsx("h1",{className:"page-title",children:"History"}),e.jsx("p",{className:"page-subtitle",children:"Changes to projects and settings."})]})}),e.jsx(s,{})]})}export{l as HistoryPage};
@@ -1,4 +1,4 @@
1
- import{r as p,u as K,o as We,j as e,L as te,D as ze,k as Ye,l as Ge,C as Re}from"./vendor-tanstack-ZXXkndVj.js";import{dY as Ze,dZ as Xe,d_ as Je,d$ as es,e0 as ss,X as $e,e1 as ts,b9 as as,y as _,cM as ns,I,B as w,aB as rs,cv as ve,cT as is,co as os,cm as ls,cH as ds,cC as ce,e2 as cs,aX as ms,aY as hs,e3 as Ie,e4 as ke,T as V,aS as Ne,aT as we,cZ as oe,e5 as us,bX as xs,e6 as ps,e7 as fs,k as Be,s as ys,f as _e,b7 as Oe}from"./index-CjowCLs3.js";import{j as gs,o as js}from"./ChartPrimitives-CZ4wVBJL.js";import{i as bs,b as vs,m as Ns,a as Fe,M as ws,A as Ps}from"./v2-overview-adapter-C7eI2iBf.js";import{Z as Cs}from"./vendor-lucide-Y6jANGfG.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";function Es(s){return s.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]+/gu)??[]}function Pe(s){return Es(s).join("\0")}function Ss(s,t){const a=Pe(s);return t.map(Pe).filter(Boolean).some(n=>n!==a&&`\0${a}\0`.includes(`\0${n}\0`))}const Ue=ss,ae={short:"target-name-short",withoutBrand:"target-name-without-brand",qualifiedWithoutName:"target-qualified-name-without-name"};function qs(s){const t=Ze(s.brandNames),a=t.length>0?Xe(t):null,n=[];return s.aliases.forEach((o,u)=>{o.trim()&&(Je(o).length<Ue?n.push({code:ae.short,field:"aliases",index:u,value:o}):a!==null&&!es(a,o)&&n.push({code:ae.withoutBrand,field:"aliases",index:u,value:o}))}),s.identityAliases?.forEach((o,u)=>{o.trim()&&(Ss(o,s.aliases)||n.push({code:ae.qualifiedWithoutName,field:"identityAliases",index:u,value:o}))}),n}function As(s){switch(s.code){case ae.short:return`"${s.value.trim()}" is too short to match safely. A name needs at least ${Ue} letters or numbers, or it can match unrelated words in an answer.`;case ae.withoutBrand:return`"${s.value.trim()}" does not include your brand name, so answers about other places with this name can count for this property.`;case ae.qualifiedWithoutName:return`"${s.value.trim()}" must include one of this property's names plus more words, such as a street or city. Publishing is refused until it does.`}}const x={heading:"Names that count as this Property",help:"An answer mentions this Property when its text contains one of these names as whole words. Source titles and source links never count, but a link in the answer whose text is one of these names does. Qualified names are longer forms, such as the name with its street or city, for a name that other places share.",names:"Names",qualifiedNames:"Qualified names",noNames:"No names are set, so answers can cite this Property but never mention it.",edit:"Edit names",save:"Save to draft",saving:"Saving…",cancel:"Cancel",namesHint:"One name per line.",qualifiedHint:"One per line. Each must include one of the names above plus more words, such as a street or city.",qualifiedNote:"With qualified names set, an answer that uses only a plain name counts as a mention only when it also cites this Property’s own page. Otherwise it is left out as not tied to one property.",draftOnly:"Saving changes the draft only. Nothing is measured differently until the setup is published.",saved:"Saved to the draft. Publish the setup to start using these names.",pending:"Name changes are saved in the draft and not published yet.",review:"Review and publish",noChanges:"No changes to save.",staleDraft:"The draft is based on an older published setup. Open measurement setup to restart it before editing names.",missingFromDraft:"This Property is not included in the current draft. Open measurement setup to review it.",conflict:"The draft changed in another session. The latest names are loaded; review them and save again.",failed:"Could not save these names. Try again."};function Ce(s){return[...new Set(s.split(`
1
+ import{r as p,u as K,o as We,j as e,L as te,D as ze,k as Ye,l as Ge,C as Re}from"./vendor-tanstack-ZXXkndVj.js";import{dY as Ze,dZ as Xe,d_ as Je,d$ as es,e0 as ss,X as $e,e1 as ts,b9 as as,y as _,cM as ns,I,B as w,aB as rs,cv as ve,cT as is,co as os,cm as ls,cH as ds,cC as ce,e2 as cs,aX as ms,aY as hs,e3 as Ie,e4 as ke,T as V,aS as Ne,aT as we,cZ as oe,e5 as us,bX as xs,e6 as ps,e7 as fs,k as Be,s as ys,f as _e,b7 as Oe}from"./index-ClA5Nf2V.js";import{j as gs,o as js}from"./ChartPrimitives-CZ4wVBJL.js";import{i as bs,b as vs,m as Ns,a as Fe,M as ws,A as Ps}from"./v2-overview-adapter-D2S25ivE.js";import{Z as Cs}from"./vendor-lucide-Y6jANGfG.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";function Es(s){return s.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}]+/gu)??[]}function Pe(s){return Es(s).join("\0")}function Ss(s,t){const a=Pe(s);return t.map(Pe).filter(Boolean).some(n=>n!==a&&`\0${a}\0`.includes(`\0${n}\0`))}const Ue=ss,ae={short:"target-name-short",withoutBrand:"target-name-without-brand",qualifiedWithoutName:"target-qualified-name-without-name"};function qs(s){const t=Ze(s.brandNames),a=t.length>0?Xe(t):null,n=[];return s.aliases.forEach((o,u)=>{o.trim()&&(Je(o).length<Ue?n.push({code:ae.short,field:"aliases",index:u,value:o}):a!==null&&!es(a,o)&&n.push({code:ae.withoutBrand,field:"aliases",index:u,value:o}))}),s.identityAliases?.forEach((o,u)=>{o.trim()&&(Ss(o,s.aliases)||n.push({code:ae.qualifiedWithoutName,field:"identityAliases",index:u,value:o}))}),n}function As(s){switch(s.code){case ae.short:return`"${s.value.trim()}" is too short to match safely. A name needs at least ${Ue} letters or numbers, or it can match unrelated words in an answer.`;case ae.withoutBrand:return`"${s.value.trim()}" does not include your brand name, so answers about other places with this name can count for this property.`;case ae.qualifiedWithoutName:return`"${s.value.trim()}" must include one of this property's names plus more words, such as a street or city. Publishing is refused until it does.`}}const x={heading:"Names that count as this Property",help:"An answer mentions this Property when its text contains one of these names as whole words. Source titles and source links never count, but a link in the answer whose text is one of these names does. Qualified names are longer forms, such as the name with its street or city, for a name that other places share.",names:"Names",qualifiedNames:"Qualified names",noNames:"No names are set, so answers can cite this Property but never mention it.",edit:"Edit names",save:"Save to draft",saving:"Saving…",cancel:"Cancel",namesHint:"One name per line.",qualifiedHint:"One per line. Each must include one of the names above plus more words, such as a street or city.",qualifiedNote:"With qualified names set, an answer that uses only a plain name counts as a mention only when it also cites this Property’s own page. Otherwise it is left out as not tied to one property.",draftOnly:"Saving changes the draft only. Nothing is measured differently until the setup is published.",saved:"Saved to the draft. Publish the setup to start using these names.",pending:"Name changes are saved in the draft and not published yet.",review:"Review and publish",noChanges:"No changes to save.",staleDraft:"The draft is based on an older published setup. Open measurement setup to restart it before editing names.",missingFromDraft:"This Property is not included in the current draft. Open measurement setup to review it.",conflict:"The draft changed in another session. The latest names are loaded; review them and save again.",failed:"Could not save these names. Try again."};function Ce(s){return[...new Set(s.split(`
2
2
  `).map(t=>t.trim()).filter(Boolean))]}function Ee(s,t){return s.length===t.length&&s.every((a,n)=>a===t[n])}function ie(s,t){return Ee(s.aliases,t.aliases)&&Ee(s.identityAliases??[],t.identityAliases??[])}function Ms(s,t,a){const{identityAliases:n,...o}=s;return a.length>0?{...o,aliases:t,identityAliases:a}:{...o,aliases:t}}function Se({label:s,names:t}){return e.jsxs("div",{className:"space-y-1",children:[e.jsx("h3",{className:"text-sm font-medium text-heading",children:s}),e.jsx("ul",{className:"space-y-1",children:t.map(a=>e.jsx("li",{className:"text-sm text-secondary",children:a},a))})]})}function qe({id:s,issues:t}){return t.length===0?null:e.jsx("ul",{id:s,className:"mt-2 space-y-1","aria-label":"Name warnings",children:t.map(a=>e.jsx("li",{className:"text-sm text-caution",children:As(a)},`${a.field}:${a.index}`))})}function Ts({projectName:s,targetKey:t,published:a,activeRevision:n,publishedBrandNames:o,service:u=vs}){const{canWrite:m}=$e(),r=p.useId(),l=K({...ts({client:_,path:{name:s}}),enabled:m}),k=K({...as({client:_,path:{name:s}}),enabled:m}),q=l.data?.draft?.authoring.targets.find(d=>d.stableKey===t),P=a.identityAliases??[],O=q!==void 0&&l.data?.draft?.baseActiveRevision===n&&!ie(q,a),T=!l.isFetching&&!k.isPending,h=k.data,A=p.useMemo(()=>h?ns(h):o,[h,o]),[C,L]=p.useState(!1),[c,j]=p.useState(""),[M,D]=p.useState(""),[ne,v]=p.useState(a),[E,R]=p.useState(null),B=`${s}\0${t}`,[H,xe]=p.useState(B);H!==B&&(xe(B),L(!1),j(""),D(""),v(a),R(null));const re=p.useRef(B);re.current=B;const W=p.useMemo(()=>Ce(c),[c]),G=p.useMemo(()=>Ce(M),[M]),pe=p.useMemo(()=>qs({aliases:W,identityAliases:G,brandNames:A}),[W,G,A]),Z=pe.filter(d=>d.field==="aliases"),X=pe.filter(d=>d.field==="identityAliases");function z(d){j(d.aliases.join(`
3
3
  `)),D((d.identityAliases??[]).join(`
4
4
  `)),v({aliases:[...d.aliases],identityAliases:[...d.identityAliases??[]]})}function g(d){return d.draft?d.draft.authoring.targets.find(S=>S.stableKey===t)??null:a}function J(){z(O?q:a),R(null),L(!0)}function y(d){d&&z(d),R({tone:"negative",text:x.conflict,review:!1})}const Y=We({mutationFn:async d=>{let S=await u.loadDraft(s);if(!S.draft){if(ie(d.names,a))return{outcome:"unchanged"};if(!ie(d.base,a))return{outcome:"conflict",latest:a};await u.createDraft(s,n),S=await u.loadDraft(s)}const U=S.draft;if(!U||!S.etag)throw new Error(x.failed);if(U.baseActiveRevision!==n)return{outcome:"stale"};const Q=U.authoring.targets.find($=>$.stableKey===t);return!Q||Q.status!=="included"?{outcome:"missing"}:ie(d.names,Q)?{outcome:"unchanged"}:ie(d.base,Q)?(await u.upsertTarget(s,S.etag,Ms(Q,d.names.aliases,d.names.identityAliases)),{outcome:"saved"}):{outcome:"conflict",latest:Q}},meta:{skipGlobalErrorToast:!0},onSuccess:(d,S)=>{if(S.openFor===re.current)switch(d.outcome){case"saved":L(!1),R({tone:"positive",text:x.saved,review:!0});return;case"unchanged":L(!1),R({tone:"positive",text:x.noChanges,review:!1});return;case"stale":R({tone:"negative",text:x.staleDraft,review:!0});return;case"missing":R({tone:"negative",text:x.missingFromDraft,review:!0});return;case"conflict":y(d.latest),l.refetch();return}},onError:(d,S)=>{if(S.openFor===re.current){if(bs(d)){y(null),l.refetch().then(U=>{U.isSuccess&&y(g(U.data))});return}R({tone:"negative",text:x.failed,review:!1})}}}),F=e.jsx(te,{to:"/projects/$projectName/portfolio",params:{projectName:s},className:"text-link underline-offset-2 hover:underline",children:x.review}),ee=a.aliases.length+P.length;return e.jsxs("section",{"aria-labelledby":"property-names",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("h2",{id:"property-names",className:"text-base font-semibold text-heading",children:x.heading}),e.jsx(I,{text:x.help})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs("p",{className:"supporting-copy",children:[ee," ",ee===1?"name":"names"]}),m&&!C?e.jsx(w,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:!T,onClick:J,children:x.edit}):null]})]}),E?e.jsxs("p",{role:E.tone==="negative"?"alert":"status",className:`mb-3 text-sm ${E.tone==="negative"?"text-negative":"text-positive"}`,children:[E.text,E.review?e.jsxs(e.Fragment,{children:[" ",F]}):null]}):O&&!C?e.jsxs("p",{role:"status",className:"mb-3 text-sm text-caution",children:[x.pending," ",F]}):null,C?e.jsxs("form",{className:"space-y-4","aria-label":"Edit names",onSubmit:d=>{d.preventDefault(),!Y.isPending&&Y.mutate({names:{aliases:W,identityAliases:G},base:ne,openFor:B})},children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:`${r}-names`,className:"block text-sm font-medium text-heading",children:x.names}),e.jsx("p",{id:`${r}-names-hint`,className:"text-sm text-secondary",children:x.namesHint}),e.jsx("textarea",{id:`${r}-names`,className:"mt-1 min-h-24 w-full rounded-md border border-strong bg-transparent px-3 py-2 text-sm text-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400","aria-describedby":`${r}-names-hint${Z.length?` ${r}-names-issues`:""}`,value:c,onChange:d=>j(d.target.value)}),e.jsx(qe,{id:`${r}-names-issues`,issues:Z}),W.length===0?e.jsx("p",{className:"mt-2 text-sm text-caution",children:x.noNames}):null]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:`${r}-qualified`,className:"block text-sm font-medium text-heading",children:x.qualifiedNames}),e.jsx("p",{id:`${r}-qualified-hint`,className:"text-sm text-secondary",children:x.qualifiedHint}),e.jsx("textarea",{id:`${r}-qualified`,className:"mt-1 min-h-20 w-full rounded-md border border-strong bg-transparent px-3 py-2 text-sm text-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400","aria-describedby":`${r}-qualified-hint ${r}-qualified-note${X.length?` ${r}-qualified-issues`:""}`,value:M,onChange:d=>D(d.target.value)}),e.jsx(qe,{id:`${r}-qualified-issues`,issues:X}),e.jsx("p",{id:`${r}-qualified-note`,className:"mt-2 max-w-3xl text-sm text-secondary",children:x.qualifiedNote})]}),e.jsx("p",{className:"text-sm text-secondary",children:x.draftOnly}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx(rs,{type:"submit",className:"h-11 px-4 text-sm md:h-11",disabled:Y.isPending,children:Y.isPending?x.saving:x.save}),e.jsx(w,{type:"button",variant:"ghost",className:"h-11 px-4 text-sm md:h-11",disabled:Y.isPending,onClick:()=>{L(!1),R(null)},children:x.cancel})]})]}):ee===0?e.jsx("p",{className:"text-sm text-secondary",children:x.noNames}):e.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[a.aliases.length>0?e.jsx(Se,{label:x.names,names:a.aliases}):null,P.length>0?e.jsx(Se,{label:x.qualifiedNames,names:P}):null]})]})}const me=50,b={branded:{headline:"When they know your name",technical:"Branded queries"},"non-brand":{headline:"When they don't",technical:"Non-brand queries"}},Ls={plan_v1:"Setup update required",no_completed_run:"No completed measurement yet",no_population:"No queries of this type are assigned",evidence_incomplete:"Source evidence is incomplete",identity_ambiguous:xs,not_applicable:"Not applicable for this Property"},Ae={complete:{label:"Measured",tone:"positive"},partial:{label:"Partly measured",tone:"caution"},running:{label:"Measuring now",tone:"neutral"},queued:{label:"Measurement queued",tone:"neutral"},failed:{label:"Measurement failed",tone:"negative"},not_measured:{label:"Not measured",tone:"neutral"}},Me={assigned:{label:"Matches this Property",tone:"positive"},sibling:{label:"Matches another Property",tone:"caution"},ownedUnmapped:{label:"Site URL not in a Property",tone:"caution"},external:{label:"External URL",tone:"neutral"},ambiguous:{label:"Matches multiple Properties",tone:"caution"},invalid:{label:"Invalid URL",tone:"negative"}};function Rs(s){return[...s].sort((t,a)=>+(a.classification==="assigned")-+(t.classification==="assigned"))}function $s(s){return`${s.expectedSlotId}:${s.usageEdgeId}`}function Is({row:s}){return s.mentioned===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(V,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"No mention signal for this Property"})]}):e.jsx(V,{tone:s.mentioned?"positive":"neutral",children:s.mentioned?"Mentioned":"Not mentioned"})}const ks="—";function Bs({row:s}){return s.cited===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(V,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"Sources were not fully captured"})]}):e.jsx(V,{tone:s.cited?"positive":"neutral",children:s.cited?"Cited":"Not cited"})}function _s({row:s}){return s.cited===null&&s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"The sources for this answer were not fully captured, so none can be shown."}):s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer returned no source URLs at all."}):e.jsxs("details",{className:"mt-2","data-answer-sources":!0,children:[e.jsxs("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[Fe," (",s.sources.length,")"]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsxs("caption",{className:"sr-only",children:["Source URLs for ",s.queryText]}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Match"}),e.jsx("th",{children:"URL"})]})}),e.jsx("tbody",{children:Rs(s.sources).map(t=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx(V,{tone:Me[t.classification].tone,children:Me[t.classification].label})}),e.jsx("td",{children:e.jsx(Be,{url:t.sourceUrl})})]},t.sourceUrl))})]})})]})}function Qe({project:s,targetKey:t,resultId:a}){const n=K({...fs({client:_,path:{name:s},query:{targetKey:t,resultId:a}})});if(n.isPending)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"status","aria-live":"polite",children:"Loading the answer…"});if(n.isError)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"alert",children:"Could not load this answer."});const o=n.data?.answer;return o==null||o.trim()===""?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer was measured, but its text was not stored."}):e.jsx("div",{className:"py-2",children:e.jsx(Ps,{headingLevel:4,copyable:!0,children:o})})}function ue(s){return Ls[s.reason]??"Not measured"}function he({metric:s,signal:t,emphasis:a=!1}){if(s.state==="unavailable")return e.jsxs("span",{className:"inline-flex flex-col gap-0.5",children:[e.jsx("span",{className:a?"text-lg font-semibold text-secondary":"text-sm font-medium text-secondary",children:"Not measured"}),e.jsx("span",{className:"text-sm text-secondary",children:ue(s)})]});const n=_e(s.value),o=s.numerator===void 0||s.denominator===void 0?null:`${s.numerator} of ${s.denominator}`,u=Oe(s,t);return e.jsxs("span",{className:"inline-flex flex-col gap-0.5 tabular-nums",children:[e.jsx("span",{className:a?"text-lg font-semibold text-heading":"text-sm font-medium text-primary",children:n}),o?e.jsx("span",{className:"text-xs text-muted",children:o}):null,u?e.jsx("span",{className:"text-xs text-muted",children:u}):null]})}function Te(s,t,a){return us({client:_,path:{name:s},query:{scope:"property",targetKey:t,queryClass:a}})}function Le(s){return s?.properties.items.at(0)}function Os({measuredAt:s,unmeasuredReason:t,queryClass:a}){const n=s===void 0?null:s===null?"No completed sweep yet":`Measured ${gs(js(s))}`;return n===null&&t===void 0?null:e.jsxs("p",{className:"supporting-copy",children:[[n,t].filter(Boolean).join(" · "),n!==null&&t===void 0?` · ${b[a].technical.toLocaleLowerCase()} only`:""]})}function Fs({project:s,groups:t}){return t.length===0?null:e.jsxs("section",{"aria-labelledby":"property-market",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Competitive comparison"}),e.jsxs("h2",{id:"property-market",className:"text-base font-semibold text-heading",children:["Measured at the market level",e.jsx(I,{text:"Competitors are attached to a market rather than to a single Property, because one building has nobody to be compared against. Share of voice and competitor pressure are reported for the market this Property sits in."})]})]}),e.jsx(w,{asChild:!0,type:"button",size:"sm",variant:"outline",children:e.jsx(te,{to:"/projects/$projectName",params:{projectName:s},search:a=>ce(oe(a),{measurementScope:"project"}),children:"Open measurement overview"})})]}),e.jsx("ul",{className:"flex flex-wrap gap-2",children:t.map(a=>e.jsxs("li",{className:"rounded-md border border-default px-3 py-1.5 text-sm text-strong",children:[a.label,e.jsxs("span",{className:"ml-2 text-xs text-muted",children:[a.competitors.length," ",a.competitors.length===1?"competitor":"competitors"]})]},a.stableKey))})]})}function de({label:s,metric:t,signal:a,failed:n=!1}){if(t===void 0)return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:n?"Unavailable":"…"}),n?e.jsx("div",{}):e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true"}),e.jsx("p",{className:"aeo-hero-row-detail",children:n?"Could not be loaded":"Loading"})]});if(t.state==="unavailable"){const l=ue(t);return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:"Not measured"}),e.jsx("div",{}),e.jsx("p",{className:"aeo-hero-row-detail",children:l==="Not measured"?"":l})]})}const{figure:o,sign:u}=ys(_e(t.value)),m=t.numerator===void 0||t.denominator===void 0?null:`${t.numerator} of ${t.denominator}`,r=Oe(t,a);return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsxs("p",{className:"aeo-hero-row-value text-heading",children:[o,u?e.jsx("span",{className:"text-faint",children:u}):null]}),e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true",children:e.jsx("div",{className:"metric-card-bar-fill progress-fill-neutral",style:{width:`${t.value*100}%`}})}),e.jsxs("p",{className:"aeo-hero-row-detail tabular-nums",children:[m??"",r?e.jsx("span",{className:"block",children:r}):null]})]})}function Us({branded:s,nonBrand:t,brandedFailed:a=!1,nonBrandFailed:n=!1}){return e.jsxs("section",{"aria-labelledby":"property-coverage-hero",children:[e.jsx("h2",{id:"property-coverage-hero",className:"sr-only",children:"Coverage for this Property"}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Non-brand · the demand to earn"}),e.jsx(de,{label:"Mentioned",metric:t?.mentionCoverage,signal:"mentioned",failed:n}),e.jsx(de,{label:"Cited",metric:t?.citationCoverage,signal:"cited",failed:n})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Branded · already named"}),e.jsx(de,{label:"Mentioned",metric:s?.mentionCoverage,signal:"mentioned",failed:a}),e.jsx(de,{label:"Cited",metric:s?.citationCoverage,signal:"cited",failed:a})]})]})]})}function Qs({branded:s,nonBrand:t,brandedError:a,nonBrandError:n,onRetry:o}){const u=[{queryClass:"branded",row:s,isError:a},{queryClass:"non-brand",row:t,isError:n}];return e.jsxs("section",{"aria-labelledby":"property-brand-contrast",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"The gap"}),e.jsxs("h2",{id:"property-brand-contrast",className:"text-base font-semibold text-heading",children:["Named versus not named",e.jsx(I,{text:"Branded queries already contain your name, so an answer engine has an easy path back to you. Non-brand queries describe the need instead, and that is the demand you have to earn. Each row is measured only over the queries assigned to this Property in that class; a class with no assigned query reads Not measured rather than 0%."})]})]})}),e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[560px]",children:[e.jsx("caption",{className:"sr-only",children:"Mention and citation coverage for this Property, split by query class"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query type"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"})]})}),e.jsx("tbody",{children:u.map(({queryClass:m,row:r,isError:l})=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:"block font-medium text-heading",children:b[m].headline}),e.jsx("span",{className:"mt-0.5 block text-xs text-muted",children:b[m].technical}),r&&l?e.jsxs("span",{className:"mt-2 flex flex-wrap items-center gap-2 text-sm text-caution",children:[e.jsx("span",{role:"status",children:"Refresh failed."}),e.jsxs(w,{type:"button",size:"sm",variant:"ghost",className:"h-11 px-3 text-sm md:h-11",onClick:()=>o(m),children:["Retry ",b[m].technical.toLocaleLowerCase()]})]}):null]}),r?e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx(he,{metric:r.mentionCoverage,signal:"mentioned",emphasis:!0})}),e.jsx("td",{children:e.jsx(he,{metric:r.citationCoverage,signal:"cited",emphasis:!0})})]}):l?e.jsx("td",{colSpan:2,children:e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{role:"alert",children:["Could not load ",b[m].technical.toLocaleLowerCase(),"."]}),e.jsxs(w,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>o(m),children:["Retry ",b[m].technical.toLocaleLowerCase()]})]})}):e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})}),e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})})]})]},m))})]})})]})}function Ks({row:s,queryClass:t,isError:a}){return e.jsxs("section",{"aria-labelledby":"property-providers",className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsx("div",{children:e.jsxs("h2",{id:"property-providers",className:"text-base font-semibold text-heading",children:["Which engines answer for this Property",e.jsx(I,{text:"Each row is measured over the queries that engine actually answered for this Property, so the rows are a split of the same population rather than parts that add up to the Property total. An engine that answered nothing for this Property is absent instead of shown at 0%."})]})})}),s===void 0&&a?e.jsxs("p",{className:"text-sm text-secondary",children:["Details for ",b[t].technical.toLocaleLowerCase()," are unavailable. Retry that query type above."]}):s===void 0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading…"}):s.providers.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No answer engine has measured ",b[t].technical.toLocaleLowerCase()," for this Property.",s.mentionCoverage.state==="unavailable"?` ${ue(s.mentionCoverage)}.`:""]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[520px]",children:[e.jsx("caption",{className:"sr-only",children:"Per-engine mention and citation coverage"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Engine"}),e.jsx("th",{children:"Mentioned"}),e.jsx("th",{children:"Cited"})]})}),e.jsx("tbody",{children:s.providers.map(n=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-medium text-heading",children:n.provider}),e.jsx("td",{children:e.jsx(he,{metric:n.mentionCoverage,signal:"mentioned"})}),e.jsx("td",{children:e.jsx(he,{metric:n.citationCoverage,signal:"cited"})})]},n.provider))})]})})]})}function Vs(s){const t=s.questions.join(" · ");return s.questionsTruncated?`${t} +${s.questionTotal-s.questions.length} more`:t}function Ds({project:s,targetKey:t,queryClass:a}){const n=K({...ps({client:_,path:{name:s},query:{targetKey:t,queryClass:a}})});if(n.isPending||n.isError)return null;const o=n.data?.competitors??[],u=n.data?.basis;return e.jsxs("section",{"aria-labelledby":"property-named-instead",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-named-instead",className:"text-base font-semibold text-heading",children:["Named instead of this Property",e.jsx(I,{text:"Counted from the answers that did not name this Property, so a name here is one an engine recommended in its place. Occurrences count answers, not positions: an engine naming the same rival in two answers counts twice, and one naming it twice in a single answer counts once."})]})}),o.length>0?e.jsxs("p",{className:"supporting-copy",children:[n.data?.total??o.length," named"]}):null]}),o.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No rival was named in the answers this Property missed. Nothing to compete with here yet."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Names the engines gave instead of this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Named"}),e.jsx("th",{children:"Answers"}),e.jsx("th",{children:"Engines"}),e.jsx("th",{children:"Queries"})]})}),e.jsx("tbody",{children:o.map(m=>e.jsxs("tr",{children:[e.jsx("td",{className:"text-strong",children:m.name}),e.jsx("td",{className:"tabular-nums text-secondary",children:m.occurrences}),e.jsxs("td",{className:"text-secondary",children:[m.providers.join(", "),m.providersTruncated?` +${m.providerTotal-m.providers.length}`:""]}),e.jsx("td",{className:"text-right",children:e.jsxs("span",{className:"inline-flex items-center justify-end gap-1",children:[e.jsx("span",{className:"tabular-nums text-secondary",children:m.questionTotal}),e.jsx(I,{text:Vs(m)})]})})]},m.name))})]})}),u?.state==="available"?e.jsxs("p",{className:"supporting-copy mt-2",children:[u.targetMissResults," of ",u.answeredResults," answers to ",b[a].technical.toLocaleLowerCase()," did not name this Property."]}):null]})]})}function Hs({questions:s,queryClass:t}){return e.jsxs("section",{"aria-labelledby":"property-questions",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-questions",className:"text-base font-semibold text-heading",children:[b[t].technical," assigned to this Property"]})}),e.jsxs("p",{className:"supporting-copy",children:[s.length," assigned"]})]}),s.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No ",b[t].technical.toLocaleLowerCase()," are assigned. Add one in advanced measurement setup to measure this class."]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Queries assigned to this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"Query"})})}),e.jsx("tbody",{children:s.map(a=>e.jsx("tr",{children:e.jsx("td",{className:"text-secondary",children:a})},a))})]})})]})}function Ws({urls:s}){return e.jsxs("section",{"aria-labelledby":"property-urls",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-urls",className:"text-base font-semibold text-heading",children:["URLs that count as this Property",e.jsx(I,{text:"A cited source URL is credited to this Property when it matches one of these. The most specific matcher wins, so a URL covered by two Properties at the same specificity is flagged for review instead of being credited to either."})]})}),e.jsxs("p",{className:"supporting-copy",children:[s.length," configured"]})]}),s.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No URLs are configured for this Property."}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"URL matchers configured for this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"URL"})})}),e.jsx("tbody",{children:s.map(t=>e.jsx("tr",{children:e.jsx("td",{className:"break-all text-secondary",children:t})},t))})]})})]})}const se={heading:"Cited on other queries",help:"Answers to queries assigned to other properties that still cited one of this Property’s own pages. This Property was not measured on those queries, so these answers are not in its Mentioned or Cited rates.",notCounted:"not in this Property’s rates",empty:"No answer to a query assigned elsewhere cited this Property’s pages in the displayed measurement.",loadError:"Citations from other queries could not be loaded.",partlySaved:"Sources partly saved"};function zs({project:s,targetKey:t,queryClass:a,runId:n,targetLabels:o}){const[u,m]=p.useState(new Set),r={client:_,path:{name:s},query:{targetKey:t,queryClass:a,shape:Ie["other-queries"],limit:me,...n?{runId:n}:{}}},l=Re({...ke(r),initialPageParam:r,getNextPageParam:h=>h.otherQueries?.nextCursor?{path:r.path,query:{...r.query,cursor:h.otherQueries.nextCursor}}:void 0}),k=l.data?.pages??[];if(k[0]?.measurement.state==="not_measured")return null;const q=k.flatMap(h=>h.otherQueries?.items??[]),P=k[0]?.otherQueries?.totalEstimate??q.length,O=h=>`${h.expectedSlotId}:${h.queryClass}`,T=b[a].technical.toLocaleLowerCase();return e.jsxs("section",{"aria-labelledby":"property-other-queries",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("h2",{id:"property-other-queries",className:"text-base font-semibold text-heading",children:se.heading}),e.jsx(I,{text:se.help})]}),l.data?e.jsxs("p",{className:"supporting-copy",children:[P," ",P===1?"answer":"answers"," · ",T," · ",se.notCounted]}):null]}),l.isPending?e.jsx("p",{className:"text-sm text-secondary",children:"Loading…"}):l.isError&&q.length===0?e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsx("span",{role:"alert",children:se.loadError}),e.jsx(w,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{l.refetch()},children:"Retry"})]}):q.length===0?e.jsx("p",{className:"text-sm text-secondary",children:se.empty}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[640px]",children:[e.jsx("caption",{className:"sr-only",children:"Answers to other properties’ queries that cited this Property’s pages"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query"}),e.jsx("th",{children:"Assigned to"}),e.jsx("th",{children:"Pages cited"}),e.jsx("th",{children:e.jsx("span",{className:"sr-only",children:"Answer"})})]})}),e.jsx("tbody",{children:q.map(h=>{const A=O(h),C=u.has(A),L=`property-other-query-${encodeURIComponent(A)}`;return e.jsxs(p.Fragment,{children:[e.jsxs("tr",{children:[e.jsxs("td",{className:"text-secondary",children:[e.jsx("span",{className:"block text-sm font-medium text-heading",children:h.queryText}),e.jsx("span",{className:"mt-1 block text-xs text-muted",children:[h.provider,h.location].filter(Boolean).join(" · ")})]}),e.jsx("td",{children:e.jsx("ul",{className:"space-y-1",children:h.assignedTargetKeys.map(c=>e.jsx("li",{children:e.jsx(te,{to:"/projects/$projectName/properties/$targetKey",params:{projectName:s,targetKey:c},search:oe,className:"text-sm text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:o.get(c)??c})},c))})}),e.jsxs("td",{children:[e.jsx("ul",{className:"space-y-1",children:h.sources.map(c=>e.jsx("li",{className:"min-w-0",children:e.jsx(Be,{url:c.sourceUrl})},c.sourceUrl))}),h.sourcesTruncated?e.jsxs("span",{className:"mt-1 block text-xs text-muted",children:[h.sourceCount," pages in total"]}):null,h.evidenceComplete?null:e.jsx("span",{className:"mt-1 block text-xs text-muted",children:se.partlySaved})]}),e.jsx("td",{className:"text-right",children:e.jsx(w,{type:"button",size:"sm",variant:"ghost",className:"h-auto min-h-11 max-w-full whitespace-normal py-2 text-left md:h-auto","aria-expanded":C,"aria-label":C?`Hide the answer for ${h.queryText}`:`Read the answer for ${h.queryText}`,"aria-controls":C?L:void 0,onClick:()=>m(c=>{const j=new Set(c);return j.delete(A)||j.add(A),j}),children:C?"Hide answer":"Read answer"})})]}),C?e.jsx("tr",{children:e.jsx("td",{id:L,colSpan:4,className:"bg-surface-subtle px-4",children:e.jsx(Qe,{project:s,targetKey:h.assignedTargetKeys[0],resultId:h.observationId})})}):null]},A)})})]})}),l.hasNextPage?e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{children:["Showing ",q.length," of ",P]}),e.jsx(w,{size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:l.isFetchingNextPage,onClick:()=>{l.fetchNextPage()},children:l.isFetchingNextPage?"Loading…":`Show ${me} more`})]}):null]})]})}function Ys(s,t){const a=[s.marketKey?t??"the selected market":null,s.provider?`the ${s.provider} answer engine`:null,s.model?`the ${s.model} model`:null,s.location?`location ${s.location}`:null,s.from||s.to?"a date range":null,s.measurementRunId?"a saved sweep":null].filter(n=>n!==null);return a.length===0?null:`AI Visibility is filtered to ${a.join(", ")}. This page shows the latest measurement for ${ws.allMarkets.toLocaleLowerCase()} and answer engines.`}function rt(){const{projectName:s,targetKey:t}=ze({strict:!1}),a=Ye(),n=Ge({strict:!1}),o=p.useMemo(()=>ve(n),[n]),[u,m]=p.useState(new Set),r=s??"",l=t??"",k=!!r&&!!l,q=p.useMemo(()=>is("portfolio",os(ls())),[]),P=k&&q,{canWrite:O}=$e(),T=K({...ds({client:_,path:{name:r}}),enabled:P}),h=T.data?.active?.plan,A=h?.schemaVersion===2?h:null,C=o.queryClass==="branded"||o.queryClass==="non-brand"?o.queryClass:null,L=i=>A?.assignments.some(f=>f.targetKey===l&&f.queryClass===i)??!1,c=C??(!L("non-brand")&&L("branded")?"branded":"non-brand");p.useEffect(()=>{!A||C||a({to:".",replace:!0,search:i=>ce(i,{queryClass:c})})},[A,C,c,a]);const j=K({...Te(r,l,"branded"),enabled:P}),M=K({...Te(r,l,"non-brand"),enabled:P}),D=Le(j.data),ne=Le(M.data),v=c==="branded"?j.data:M.data,E=c==="branded"?D:ne,B=(c==="branded"?j.isError:M.isError)&&E===void 0,H=v?.measurement.displayedRunId;cs(r,{view:"property",selection:{mode:"advanced",scope:"property",scopeKey:l,queryClass:c,limit:10,...H?{runId:H}:{}}});const xe=E?.mentionCoverage.state==="unavailable"?ue(E.mentionCoverage):void 0,re=v===void 0?void 0:v.measurement.completedAt??null,W=v!==void 0&&(v.measurement.state==="not_measured"||v.nextAction.kind==="run_measurement"),G=i=>ce(oe(i),{measurementScope:"property",measurementScopeKey:l,queryClass:c,measurementRunId:void 0,measurementRevision:void 0,measurementTo:void 0}),Z=K({...ms({client:_,path:{name:r},query:hs(ve(G(n)))}),enabled:P&&W,retry:!1}).data,X=Z!==void 0&&Z.selection.measurement.measuredRevision!==null&&(Z.populations.find(i=>i.queryClass===c)?.summary.queryCount??0)>0,z={client:_,path:{name:r},query:{targetKey:l,queryClass:c,shape:Ie.answers,limit:me,...H?{runId:H}:{}}},g=Re({...ke(z),enabled:P&&v!==void 0,initialPageParam:z,getNextPageParam:i=>i.answers?.nextCursor?{path:z.path,query:{...z.query,cursor:i.answers.nextCursor}}:void 0}),J=T.data?.active??null,y=J?.plan.schemaVersion===2?J.plan:null,Y=J!==null&&y===null,F=y?.targets.find(i=>i.stableKey===l)??null,ee=Ys(o,y?.reportingScopes?.find(i=>i.stableKey===o.marketKey)?.label),d=p.useMemo(()=>{if(!y)return[];const i=new Map(y.querySnapshots.map(f=>[f.queryId,f.queryText]));return[...new Set(y.assignments.filter(f=>f.targetKey===l&&f.queryClass===c).flatMap(f=>{const N=i.get(f.queryId);return N===void 0?[]:[N]}))].sort((f,N)=>f.localeCompare(N))},[y,l,c]),S=p.useMemo(()=>F?.urlMatchers.map(Ns)??[],[F]),U=p.useMemo(()=>new Map((y?.targets??[]).map(i=>[i.stableKey,i.label])),[y]),Q=p.useMemo(()=>y?.groups.filter(i=>i.targetKeys.includes(l))??[],[y,l]),$=p.useMemo(()=>(g.data?.pages??[]).flatMap(N=>N.answers?.items??[]),[g.data]),ye=g.data?.pages[0]?.answers?.totalEstimate??$.length,Ke=(g.data?.pages??[]).length>0&&(g.data?.pages??[]).every(i=>i.answers===void 0),Ve=g.data?.pages[0]?.measurement.state,le=e.jsxs(te,{to:"/projects/$projectName",params:{projectName:r},search:oe,className:"inline-flex items-center gap-1 text-xs text-muted hover:text-strong",children:[e.jsx(Cs,{className:"size-3.5","aria-hidden":"true"}),"Back to AI Visibility"]});if(!k)return e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"Missing project name or Property key in URL."})});if(!q)return e.jsxs("div",{className:"page-container space-y-3",children:[le,e.jsx("p",{className:"text-sm text-muted",children:"This view is not available here."})]});if(T.isPending&&!T.isError)return e.jsx("div",{className:"page-container",children:e.jsxs("div",{role:"status","aria-live":"polite",children:[e.jsx("span",{className:"sr-only",children:"Loading Property"}),e.jsx("div",{className:"h-32 animate-pulse rounded-md bg-surface-subtle","aria-hidden":"true"})]})});const De=T.isError&&T.data===void 0,ge=j.isError&&j.data===void 0,je=M.isError&&M.data===void 0;return De||ge&&je?e.jsxs("div",{className:"page-container space-y-3",children:[le,e.jsx("p",{role:"alert",className:"text-sm text-negative",children:"Could not load this Property."}),e.jsx(w,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{T.refetch(),j.refetch(),M.refetch()},children:"Try again"})]}):!y||!F?e.jsxs("div",{className:"page-container space-y-3",children:[le,e.jsx("p",{role:"status",className:"text-sm text-secondary",children:y?"This Property is not in the published setup. It may have been renamed or removed.":"A Property page needs a published advanced measurement setup. Republish setup from the project Portfolio tab."}),e.jsx(w,{asChild:!0,type:"button",variant:"outline",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(te,{to:"/projects/$projectName/portfolio",params:{projectName:r},children:O?Y?"Republish setup":"Open measurement setup":"View measurement setup"})})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[le,e.jsx("h1",{className:"page-title mt-2",children:F.label}),e.jsxs("p",{className:"page-subtitle",children:["Property in ",r,ee?e.jsxs(e.Fragment,{children:[" · Filters not applied ",e.jsx(I,{text:ee})]}):null]})]}),e.jsxs("div",{className:"page-header-right",children:[v?e.jsx(V,{tone:Ae[v.measurement.state].tone,children:Ae[v.measurement.state].label}):null,E&&E.flags>0?e.jsxs(V,{tone:"caution",children:[E.flags," flagged"]}):null]})]}),e.jsx(Us,{branded:D,nonBrand:ne,brandedFailed:ge,nonBrandFailed:je}),e.jsx(Qs,{branded:D,nonBrand:ne,brandedError:j.isError,nonBrandError:M.isError,onRetry:i=>{i==="branded"?j.refetch():M.refetch()}}),W?e.jsxs("section",{className:"flex flex-wrap items-center justify-between gap-3 border-y border-default py-4","aria-label":"Measurement next step",children:[e.jsx("p",{className:"text-sm text-secondary",children:we()?Ne:O?`Run a measurement from the project overview to collect this Property’s coverage and source evidence.${X?" AI Visibility still shows the last results.":""}`:"This Property needs a new measurement before coverage and source evidence are available."}),e.jsx(w,{asChild:!0,type:"button",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(te,{to:"/projects/$projectName",params:{projectName:r},search:X?G:oe,children:X?"See the last results":O?"Go to AI Visibility":"View AI Visibility"})})]}):null,e.jsxs("div",{className:"flex flex-wrap items-end gap-4 border-y border-default py-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"property-query-class",className:"block text-sm font-medium text-heading",children:"Query type"}),e.jsxs("select",{id:"property-query-class",value:c,onChange:i=>{const f=i.target.value==="branded"?"branded":"non-brand";a({to:".",search:N=>ce(N,{queryClass:f})})},className:"h-11 rounded-md border border-default bg-surface px-3 text-sm text-primary focus:outline-none focus:ring-2 focus:ring-mono-400",children:[e.jsx("option",{value:"non-brand",children:b["non-brand"].technical}),e.jsx("option",{value:"branded",children:b.branded.technical})]})]}),e.jsx(Os,{measuredAt:re,unmeasuredReason:xe,queryClass:c})]}),e.jsx(Ks,{row:E,queryClass:c,isError:B}),e.jsx(Ds,{project:r,targetKey:l,queryClass:c}),e.jsx(Hs,{questions:d,queryClass:c}),e.jsx(Ts,{projectName:r,targetKey:l,published:F,activeRevision:J.revision,publishedBrandNames:y.identities.projectBrand.names}),e.jsx(Ws,{urls:S}),e.jsx(Fs,{project:r,groups:Q}),e.jsxs("section",{"aria-labelledby":"property-evidence",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-evidence",className:"text-base font-semibold text-heading",children:["Answers the engines gave",e.jsx(I,{text:"One row per answer an engine gave for the queries assigned to this Property in the displayed measurement. Mentioned and cited are independent: an answer can name this Property without linking it, or link it without naming it. Answers that did neither are listed first, because those are what a gap is made of. Where the answer text was not stored the mention reads Not measured, never a zero. Open a row to read what the engine actually said, followed by the source URLs it returned, this Property's own first. The answer is where a miss becomes actionable: a query this Property was not named in may still have named a sibling building."})]})}),$.length>0?e.jsxs("p",{className:"supporting-copy",children:[$.length," of ",ye]}):null]}),B?e.jsxs("p",{className:"text-sm text-secondary",children:["Evidence for ",b[c].technical.toLocaleLowerCase()," is unavailable. Retry that query type above."]}):g.isPending&&$.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading evidence…"}):g.isError&&$.length===0?e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsx("span",{role:"alert",children:"Evidence could not be loaded."}),e.jsx(w,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{g.refetch()},children:"Retry evidence"})]}):Ve==="not_measured"?e.jsx("p",{className:"text-sm text-secondary",children:we()?Ne:"Not measured yet. Run a measurement to collect the answers for this Property."}):Ke?e.jsx("p",{role:"alert",className:"text-sm text-caution",children:"This measurement was returned in an older format, so the answers cannot be shown here. The numbers above are unaffected."}):$.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No answers matched this Property in the displayed measurement."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"property-answer-table-container overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table property-evidence-table",children:[e.jsx("caption",{className:"sr-only",children:"Answers measured for this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"}),e.jsx("th",{children:"Sources"}),e.jsx("th",{children:e.jsx("span",{className:"sr-only",children:"Sources detail"})})]})}),e.jsx("tbody",{children:$.map(i=>{const f=$s(i),N=u.has(f),be=`property-answer-${encodeURIComponent(f)}`;return e.jsxs(p.Fragment,{children:[e.jsxs("tr",{className:"property-answer-summary",children:[e.jsxs("td",{className:"text-secondary",children:[e.jsx("h3",{className:"text-sm font-medium text-heading",children:i.queryText}),e.jsx("span",{className:"mt-1 block text-xs text-muted",children:[i.provider,i.location].filter(Boolean).join(" · ")}),i.historical||i.bridged?e.jsx("span",{className:"mt-1 flex",children:e.jsx(V,{tone:"caution",children:"Historical"})}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Mentioned"}),e.jsx(Is,{row:i})]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Cited"}),e.jsx(Bs,{row:i})]}),e.jsxs("td",{className:"tabular-nums text-secondary",children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:Fe}),i.cited===null?ks:i.sources.length]}),e.jsx("td",{className:"text-right",children:e.jsx(w,{type:"button",size:"sm",variant:"ghost",className:"h-auto min-h-11 max-w-full whitespace-normal py-2 text-left md:h-auto","aria-expanded":N,"aria-label":N?`Hide the answer for ${i.queryText}`:`Read the answer for ${i.queryText}`,"aria-controls":N?be:void 0,onClick:()=>m(He=>{const fe=new Set(He);return fe.delete(f)||fe.add(f),fe}),children:N?"Hide answer":"Read answer"})})]}),N?e.jsx("tr",{className:"property-answer-detail",children:e.jsxs("td",{id:be,colSpan:5,className:"bg-surface-subtle px-4",children:[e.jsx(Qe,{project:r,targetKey:l,resultId:i.observationId}),e.jsx(_s,{row:i})]})}):null]},f)})})]})}),g.hasNextPage?e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{children:["Showing ",$.length," of ",ye]}),g.isFetchNextPageError?e.jsx("span",{role:"alert",children:"Could not load more evidence."}):null,e.jsx(w,{size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:g.isFetchingNextPage,onClick:()=>{g.fetchNextPage()},children:g.isFetchingNextPage?"Loading…":g.isFetchNextPageError?"Retry more evidence":`Show ${me} more`})]}):null]})]}),v?e.jsx(zs,{project:r,targetKey:l,queryClass:c,runId:H,targetLabels:U}):null]})}export{Me as EVIDENCE_LABELS,rt as MeasurementPropertyPage,se as OTHER_QUERIES_COPY};