@canonry/canonry 7.4.0 → 7.5.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 (31) hide show
  1. package/assets/assets/{AuditHistoryPanel-DIL5oTHF.js → AuditHistoryPanel-B5aLMnWE.js} +1 -1
  2. package/assets/assets/{BacklinksPage-BpCURZh8.js → BacklinksPage-Biq1jrqe.js} +1 -1
  3. package/assets/assets/{HistoryPage-TPbexxzA.js → HistoryPage-CGGkAgnz.js} +1 -1
  4. package/assets/assets/MeasurementPropertyPage-BwyWGGBg.js +1 -0
  5. package/assets/assets/ProjectPage-DEnKyD3e.js +8 -0
  6. package/assets/assets/{RunsPage-Dhu7Qe7B.js → RunsPage-DNBn0Rau.js} +1 -1
  7. package/assets/assets/{SettingsPage-BCG1QJ07.js → SettingsPage-D3m-BLuf.js} +1 -1
  8. package/assets/assets/{SiteHealthSection-BXueYSiu.js → SiteHealthSection-CPMu1l-l.js} +3 -3
  9. package/assets/assets/{TrafficPage-ua9wsccA.js → TrafficPage-BCK_V__i.js} +2 -2
  10. package/assets/assets/{TrafficSourceDetailPage-pwATnkp8.js → TrafficSourceDetailPage-DaCehUm8.js} +1 -1
  11. package/assets/assets/{extract-error-message-DJfNdKqh.js → extract-error-message-CqBLzzuR.js} +1 -1
  12. package/assets/assets/{index-DvWWyhGp.js → index-C2X_UARl.js} +15 -15
  13. package/assets/assets/{react-sigma_core.esm.min-DnbWY5j_.js → react-sigma_core.esm.min-BvO4SZKT.js} +1 -1
  14. package/assets/assets/v2-overview-adapter-CgDChBa5.js +1 -0
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-PXRUWG75.js → chunk-3L7QPB37.js} +68 -5
  17. package/dist/{chunk-TNLOOXUP.js → chunk-6Z5MRX24.js} +2 -2
  18. package/dist/{chunk-ZP6GF32R.js → chunk-E7EWAAH3.js} +3 -3
  19. package/dist/{chunk-JU6TPMCJ.js → chunk-JURAGZOO.js} +2 -2
  20. package/dist/{chunk-XFVJ6QVE.js → chunk-KS66E5H6.js} +2 -2
  21. package/dist/{chunk-GEKMHZS2.js → chunk-OY5QVO34.js} +6 -6
  22. package/dist/{chunk-SWSWCUHS.js → chunk-ZHI2MCMD.js} +58 -30
  23. package/dist/cli.js +26 -15
  24. package/dist/{demo-server-INMOE4BA.js → demo-server-55M7DF3U.js} +4 -4
  25. package/dist/index.js +6 -6
  26. package/dist/{intelligence-service-IBUS2IND.js → intelligence-service-HZSRDMFP.js} +2 -2
  27. package/dist/mcp.js +4 -4
  28. package/package.json +10 -10
  29. package/assets/assets/MeasurementPropertyPage-H991GW9h.js +0 -1
  30. package/assets/assets/ProjectPage-l1NAl-9k.js +0 -8
  31. package/assets/assets/v2-overview-adapter-BIOvZAlo.js +0 -1
@@ -1,4 +1,4 @@
1
- import{g as Bt,t as S,r as C}from"./vendor-tanstack-ZXXkndVj.js";import{e as Ht,G as Wt}from"./SiteHealthSection-BXueYSiu.js";import"./index-DvWWyhGp.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-lucide-N6vOpZmh.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-CYlrwLJs.js";function Vt(r,n){if(typeof r!="object"||!r)return r;var i=r[Symbol.toPrimitive];if(i!==void 0){var e=i.call(r,n);if(typeof e!="object")return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}function ae(r){var n=Vt(r,"string");return typeof n=="symbol"?n:n+""}function A(r,n){if(!(r instanceof n))throw new TypeError("Cannot call a class as a function")}function He(r,n){for(var i=0;i<n.length;i++){var e=n[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(r,ae(e.key),e)}}function L(r,n,i){return n&&He(r.prototype,n),i&&He(r,i),Object.defineProperty(r,"prototype",{writable:!1}),r}function Q(r){return Q=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(n){return n.__proto__||Object.getPrototypeOf(n)},Q(r)}function yt(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(yt=function(){return!!r})()}function jt(r){if(r===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}function Zt(r,n){if(n&&(typeof n=="object"||typeof n=="function"))return n;if(n!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return jt(r)}function I(r,n,i){return n=Q(n),Zt(r,yt()?Reflect.construct(n,i||[],Q(r).constructor):n.apply(r,i))}function xe(r,n){return xe=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,e){return i.__proto__=e,i},xe(r,n)}function G(r,n){if(typeof n!="function"&&n!==null)throw new TypeError("Super expression must either be null or a function");r.prototype=Object.create(n&&n.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),Object.defineProperty(r,"prototype",{writable:!1}),n&&xe(r,n)}function qt(r){if(Array.isArray(r))return r}function Yt(r,n){var i=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(i!=null){var e,t,a,o,s=[],l=!0,h=!1;try{if(a=(i=i.call(r)).next,n===0){if(Object(i)!==i)return;l=!1}else for(;!(l=(e=a.call(i)).done)&&(s.push(e.value),s.length!==n);l=!0);}catch(u){h=!0,t=u}finally{try{if(!l&&i.return!=null&&(o=i.return(),Object(o)!==o))return}finally{if(h)throw t}}return s}}function Se(r,n){(n==null||n>r.length)&&(n=r.length);for(var i=0,e=Array(n);i<n;i++)e[i]=r[i];return e}function Tt(r,n){if(r){if(typeof r=="string")return Se(r,n);var i={}.toString.call(r).slice(8,-1);return i==="Object"&&r.constructor&&(i=r.constructor.name),i==="Map"||i==="Set"?Array.from(r):i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Se(r,n):void 0}}function Xt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
1
+ import{g as Bt,t as S,r as C}from"./vendor-tanstack-ZXXkndVj.js";import{e as Ht,G as Wt}from"./SiteHealthSection-CPMu1l-l.js";import"./index-C2X_UARl.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-D-cUuLZo.js";import"./vendor-lucide-N6vOpZmh.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-CYlrwLJs.js";function Vt(r,n){if(typeof r!="object"||!r)return r;var i=r[Symbol.toPrimitive];if(i!==void 0){var e=i.call(r,n);if(typeof e!="object")return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}function ae(r){var n=Vt(r,"string");return typeof n=="symbol"?n:n+""}function A(r,n){if(!(r instanceof n))throw new TypeError("Cannot call a class as a function")}function He(r,n){for(var i=0;i<n.length;i++){var e=n[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(r,ae(e.key),e)}}function L(r,n,i){return n&&He(r.prototype,n),i&&He(r,i),Object.defineProperty(r,"prototype",{writable:!1}),r}function Q(r){return Q=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(n){return n.__proto__||Object.getPrototypeOf(n)},Q(r)}function yt(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(yt=function(){return!!r})()}function jt(r){if(r===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}function Zt(r,n){if(n&&(typeof n=="object"||typeof n=="function"))return n;if(n!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return jt(r)}function I(r,n,i){return n=Q(n),Zt(r,yt()?Reflect.construct(n,i||[],Q(r).constructor):n.apply(r,i))}function xe(r,n){return xe=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,e){return i.__proto__=e,i},xe(r,n)}function G(r,n){if(typeof n!="function"&&n!==null)throw new TypeError("Super expression must either be null or a function");r.prototype=Object.create(n&&n.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),Object.defineProperty(r,"prototype",{writable:!1}),n&&xe(r,n)}function qt(r){if(Array.isArray(r))return r}function Yt(r,n){var i=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(i!=null){var e,t,a,o,s=[],l=!0,h=!1;try{if(a=(i=i.call(r)).next,n===0){if(Object(i)!==i)return;l=!1}else for(;!(l=(e=a.call(i)).done)&&(s.push(e.value),s.length!==n);l=!0);}catch(u){h=!0,t=u}finally{try{if(!l&&i.return!=null&&(o=i.return(),Object(o)!==o))return}finally{if(h)throw t}}return s}}function Se(r,n){(n==null||n>r.length)&&(n=r.length);for(var i=0,e=Array(n);i<n;i++)e[i]=r[i];return e}function Tt(r,n){if(r){if(typeof r=="string")return Se(r,n);var i={}.toString.call(r).slice(8,-1);return i==="Object"&&r.constructor&&(i=r.constructor.name),i==="Map"||i==="Set"?Array.from(r):i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Se(r,n):void 0}}function Xt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
2
2
  In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ee(r,n){return qt(r)||Yt(r,n)||Tt(r,n)||Xt()}var pe={black:"#000000",silver:"#C0C0C0",gray:"#808080",grey:"#808080",white:"#FFFFFF",maroon:"#800000",red:"#FF0000",purple:"#800080",fuchsia:"#FF00FF",green:"#008000",lime:"#00FF00",olive:"#808000",yellow:"#FFFF00",navy:"#000080",blue:"#0000FF",teal:"#008080",aqua:"#00FFFF",darkblue:"#00008B",mediumblue:"#0000CD",darkgreen:"#006400",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",springgreen:"#00FF7F",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",rebeccapurple:"#663399",mediumaquamarine:"#66CDAA",dimgray:"#696969",dimgrey:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",slategrey:"#708090",lightslategray:"#778899",lightslategrey:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370DB",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",darkgrey:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgray:"#D3D3D3",lightgrey:"#D3D3D3",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",palevioletred:"#DB7093",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",lightyellow:"#FFFFE0",ivory:"#FFFFF0"},Ct=new Int8Array(4),be=new Int32Array(Ct.buffer,0,1),$t=new Float32Array(Ct.buffer,0,1),Kt=/^\s*rgba?\s*\(/,Jt=/^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/;function Qt(r){var n=0,i=0,e=0,t=1;if(r[0]==="#")r.length===4?(n=parseInt(r.charAt(1)+r.charAt(1),16),i=parseInt(r.charAt(2)+r.charAt(2),16),e=parseInt(r.charAt(3)+r.charAt(3),16)):(n=parseInt(r.charAt(1)+r.charAt(2),16),i=parseInt(r.charAt(3)+r.charAt(4),16),e=parseInt(r.charAt(5)+r.charAt(6),16)),r.length===9&&(t=parseInt(r.charAt(7)+r.charAt(8),16)/255);else if(Kt.test(r)){var a=r.match(Jt);a&&(n=+a[1],i=+a[2],e=+a[3],a[4]&&(t=+a[4]))}return{r:n,g:i,b:e,a:t}}var J={};for(var le in pe)J[le]=oe(pe[le]),J[pe[le]]=J[le];function Rt(r,n,i,e,t){return be[0]=e<<24|i<<16|n<<8|r,be[0]=be[0]&4278190079,$t[0]}function oe(r){if(r=r.toLowerCase(),typeof J[r]<"u")return J[r];var n=Qt(r),i=n.r,e=n.g,t=n.b,a=n.a;a=a*255|0;var o=Rt(i,e,t,a);return J[r]=o,o}var Ee={};function _t(r){if(typeof Ee[r]<"u")return Ee[r];var n=(r&16711680)>>>16,i=(r&65280)>>>8,e=r&255,t=255,a=Rt(n,i,e,t);return Ee[r]=a,a}function We(r,n,i,e){return i+(n<<8)+(r<<16)}function Ve(r,n,i,e,t,a){var o=Math.floor(i/a*t),s=Math.floor(r.drawingBufferHeight/a-e/a*t),l=new Uint8Array(4);r.bindFramebuffer(r.FRAMEBUFFER,n),r.readPixels(o,s,1,1,r.RGBA,r.UNSIGNED_BYTE,l);var h=ee(l,4),u=h[0],d=h[1],f=h[2],g=h[3];return[u,d,f,g]}function c(r,n,i){return(n=ae(n))in r?Object.defineProperty(r,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):r[n]=i,r}function je(r,n){var i=Object.keys(r);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(r);n&&(e=e.filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})),i.push.apply(i,e)}return i}function b(r){for(var n=1;n<arguments.length;n++){var i=arguments[n]!=null?arguments[n]:{};n%2?je(Object(i),!0).forEach(function(e){c(r,e,i[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):je(Object(i)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))})}return r}function ei(r,n){for(;!{}.hasOwnProperty.call(r,n)&&(r=Q(r))!==null;);return r}function Ae(){return Ae=typeof Reflect<"u"&&Reflect.get?Reflect.get.bind():function(r,n,i){var e=ei(r,n);if(e){var t=Object.getOwnPropertyDescriptor(e,n);return t.get?t.get.call(arguments.length<3?r:i):t.value}},Ae.apply(null,arguments)}function wt(r,n,i,e){var t=Ae(Q(r.prototype),n,i);return typeof t=="function"?function(a){return t.apply(i,a)}:t}function ti(r){return r.normalized?1:r.size}function ye(r){var n=0;return r.forEach(function(i){return n+=ti(i)}),n}function xt(r,n,i){var e=r==="VERTEX"?n.VERTEX_SHADER:n.FRAGMENT_SHADER,t=n.createShader(e);if(t===null)throw new Error("loadShader: error while creating the shader");n.shaderSource(t,i),n.compileShader(t);var a=n.getShaderParameter(t,n.COMPILE_STATUS);if(!a){var o=n.getShaderInfoLog(t);throw n.deleteShader(t),new Error(`loadShader: error while compiling the shader:
3
3
  `.concat(o,`
4
4
  `).concat(i))}return t}function ii(r,n){return xt("VERTEX",r,n)}function ri(r,n){return xt("FRAGMENT",r,n)}function ni(r,n){var i=r.createProgram();if(i===null)throw new Error("loadProgram: error while creating the program.");var e,t;for(e=0,t=n.length;e<t;e++)r.attachShader(i,n[e]);r.linkProgram(i);var a=r.getProgramParameter(i,r.LINK_STATUS);if(!a){var o=r.getProgramInfoLog(i);throw r.deleteProgram(i),new Error("loadProgram: error while linking the program: ".concat(o))}return i}function Ze(r){var n=r.gl,i=r.buffer,e=r.program,t=r.vertexShader,a=r.fragmentShader;n.deleteShader(t),n.deleteShader(a),n.deleteProgram(e),n.deleteBuffer(i)}var qe=`#define PICKING_MODE
@@ -0,0 +1 @@
1
+ import{r as j,j as i}from"./vendor-tanstack-ZXXkndVj.js";import{Q as ae,eh as oe,B as le,aZ as ue}from"./index-C2X_UARl.js";import{M as ce}from"./vendor-markdown-B4giJcws.js";import{C as de,$ as pe,g as J}from"./vendor-lucide-N6vOpZmh.js";const Ae="Sources",B={copy:"Copy answer",copying:"Copying…",copied:"Copied",failed:"Could not copy. Select and copy the answer above."};function me({previewLength:e,highlight:r}){return o=>{if(e!==void 0&&Number.isFinite(e)){let c=Math.max(0,Math.floor(e));const d={field:"value",omitted:!1},p=n=>{if(n.type==="definition")return!0;if(n.children)return n.children=n.children.filter(p),n.children.length>0;const s=n.type==="image"||n.type==="imageReference"?"alt":"value",f=n[s];if(f===void 0)return c>0;const b=Array.from(f);if(b.length===0)return c>0;if(c===0)return d.omitted=!0,!1;const N=b.length>c,k=b.slice(0,c);if(N&&!/\s/.test(b[c])){let g=k.length-1;for(;g>=0&&!/\s/.test(k[g]);)g--;g>=0&&g>c-40&&(k.length=g)}return d.omitted||=N,n[s]=k.join(""),c=N?0:c-k.length,k.length===0?!1:(d.lastNode=n,d.field=s,!0)};p(o),d.omitted&&(d.lastNode?d.lastNode[d.field]=`${d.lastNode[d.field].trimEnd()}…`:o.children?.push({type:"paragraph",children:[{type:"text",value:"…"}]}))}if(r){const c=d=>{["link","linkReference","code","inlineCode"].includes(d.type)||(d.type==="text"&&(d.data={...d.data,hName:"span"}),d.children?.forEach(c))};c(o)}}}function fe({headingLevel:e}){return r=>{const o=[],c=p=>{p.type==="heading"&&p.depth&&o.push(p),p.children?.forEach(c)};c(r);const d=o.reduce((p,n)=>Math.min(p,n.depth),6);for(const p of o){const n=p.depth-d;p.depth=Math.min(6,e+n),p.data={...p.data,hProperties:{...p.data?.hProperties,"data-answer-heading-level":n+1}}}}}function ge({answer:e}){const[r,o]=j.useState("idle"),c=j.useRef(!1),d=async()=>{if(!c.current){c.current=!0,o("copying");try{await navigator.clipboard.writeText(e),o("copied")}catch{o("failed")}finally{c.current=!1}}};return i.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-x-3",children:[i.jsx(le,{type:"button",variant:"ghost",className:"min-h-11 px-2","aria-disabled":r==="copying","aria-busy":r==="copying",onClick:()=>{d()},children:r==="copying"?B.copying:B.copy}),i.jsx("span",{role:"status",className:"text-sm text-secondary",children:r==="copied"?B.copied:r==="failed"?B.failed:""})]})}const Se=j.memo(function({children:r,headingLevel:o=4,copyable:c=!1,highlightGroups:d,previewLength:p}){return i.jsxs("div",{className:"answer-markdown",children:[i.jsx(ce,{remarkPlugins:[[fe,{headingLevel:o}],[me,{previewLength:p,highlight:!!d?.length}]],components:{p:({children:n})=>i.jsx("p",{className:"mb-3 whitespace-pre-wrap last:mb-0",children:n}),ul:({children:n})=>i.jsx("ul",{className:"mb-3 ml-5 list-disc space-y-1",children:n}),ol:({children:n,start:s})=>i.jsx("ol",{start:s,className:"mb-3 ml-5 list-decimal space-y-1",children:n}),pre:({children:n})=>i.jsx("pre",{className:"mb-3 overflow-x-auto whitespace-pre-wrap",children:n}),span:({children:n})=>i.jsx("span",{children:typeof n=="string"&&d?n.split(/(https?:\/\/[^\s<>]+)/i).map((s,f)=>f%2?s:i.jsx(j.Fragment,{children:oe(s,d)},f)):n}),a:({children:n,href:s})=>{const f=ae(s);return f?i.jsx("a",{href:f,target:"_blank",rel:"noopener noreferrer",className:"text-link underline",children:n}):i.jsx("span",{children:n})},img:({alt:n})=>i.jsx("span",{children:n})},children:r}),c&&r.trim()?i.jsx(ge,{answer:r},r):null]})}),X="min-h-11 w-full rounded-md border border-default bg-surface px-3 py-2 text-sm text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",G="flex min-h-11 w-full items-center justify-between gap-3 rounded px-2 text-left text-sm text-primary hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",E=e=>e.kind==="project"?"Whole site":e.label,q={allMarkets:"All markets",browse:e=>`Browse ${e}`,select:e=>`Select ${e}`,browseAll:"Browse all properties"},he=e=>e?.kind==="group"&&e.marketKeys?.length===1?e.marketKeys[0]:void 0,ee=e=>`${e} ${e===1?"property":"properties"}`;function Ke({options:e,selected:r,onSelect:o,marketKey:c,label:d="Measurement scope",labelVisibility:p="visible",allowGroupSelect:n=!0}){const s=[...e].sort((t,u)=>t.label.localeCompare(u.label,void 0,{numeric:!0})||t.id.localeCompare(u.id)),[f,b]=j.useState(""),[N,k]=j.useState([]),[g,$]=j.useState(!1),C=j.useRef(null),I=j.useRef(null),a=j.useId(),y=s.filter(t=>t.kind==="group"),h=new Map(y.map(t=>[t.id,t])),l=h.get(N.at(-1)??""),F=h.get(N.at(-2)??""),x=f.trim().toLocaleLowerCase(),ne=y.filter(t=>!t.parentGroupIds?.some(u=>h.has(u))),_=s.filter(t=>t.kind==="property"),O=t=>(t.parentGroupIds??[]).map(u=>h.get(u)?.label).filter(Boolean).join(" · "),P=t=>`${E(t)} ${O(t)}`.toLocaleLowerCase().includes(x),U=t=>{const u=[...t.parentGroupIds??[]],m=new Set;for(;u.length;){const v=u.pop();if(v===l?.id)return!0;m.has(v)||(m.add(v),u.push(...h.get(v)?.parentGroupIds??[]))}return!1},A=(g?[]:l?y.filter(t=>x?U(t):t.parentGroupIds?.includes(l.id)):x?y:ne).filter(P),S=s.find(t=>t.kind==="market"&&t.id===(c??(r.kind==="market"?r.id:void 0))),H=l&&S&&(l.marketKeys?.includes(S.id)||S.parentGroupIds?.includes(l.id))?S.id:void 0,L=n?H??he(l):void 0,V=(l?_.filter(t=>t.parentGroupIds?.includes(l.id)&&(!L||t.marketKeys?.includes(L))):x||g||y.length===0?_:[]).filter(P),W=s.filter(t=>t.kind!=="market"||g||!n&&!l&&!x&&y.length>0||n&&l?.marketKeys?.length===1&&!x?!1:(l?x?U(t):t.parentGroupIds?.includes(l.id):x||!t.parentGroupIds?.some(m=>h.has(m)))&&P(t)),Y=l||g?[]:s.filter(t=>t.kind==="project"&&P(t));j.useEffect(()=>{const t=u=>{C.current?.open&&u.target instanceof Node&&!C.current.contains(u.target)&&(C.current.open=!1)};return document.addEventListener("pointerdown",t),()=>document.removeEventListener("pointerdown",t)},[]);const se=t=>{C.current&&(C.current.open=!1,C.current.querySelector("summary")?.focus());const u=n?t.kind==="property"?L:t.kind==="group"&&t.id===l?.id?H:void 0:void 0;u?o(t,u):o(t)},T=t=>{const u=[];let m=h.get(t.parentGroupIds?.[0]??"");for(;m&&!u.includes(m.id)&&m.id!==t.id;)u.unshift(m.id),m=h.get(m.parentGroupIds?.[0]??"");return[...u,t.id]},ie=()=>{const t=r.kind==="group"?h.get(r.id):void 0,u=h.get(S?.parentGroupIds?.[0]??""),m=(r.parentGroupIds??[]).flatMap(K=>{const R=h.get(K);return R?[T(R)]:[]}),v=m.find(K=>K.at(-1)===l?.id)??m.sort((K,R)=>R.length-K.length)[0]??[],Z=u?T(u):r.marketKeys?.length?[]:v;k(t?T(t):Z),$(r.kind==="property"&&Z.length===0&&y.length>0),b("")},z=t=>{k(T(t)),$(!1),b(""),I.current?.focus()},w=(t,u=E(t))=>i.jsxs("div",{className:"flex items-stretch",children:[i.jsxs("button",{type:"button",className:G,"aria-label":t.kind==="group"&&!n?q.browse(E(t)):q.select(E(t)),"aria-current":r.kind===t.kind&&r.id===t.id?"true":void 0,onClick:()=>t.kind==="group"&&!n?z(t):se(t),children:[i.jsxs("span",{className:"min-w-0 break-words",children:[u,x&&O(t)?i.jsx("span",{className:"block text-[13px] text-secondary",children:O(t)}):null]}),i.jsx("span",{className:"shrink-0 text-right text-[13px] text-secondary",children:t.kind==="market"?n?"Query context":"Market":t.kind==="property"?"Property":ee(t.targetCount)})]}),n&&t.kind==="group"&&t.id!==l?.id&&s.some(m=>m.parentGroupIds?.includes(t.id))?i.jsx("button",{type:"button","aria-label":q.browse(t.label),title:`Browse ${t.label}`,className:"flex min-h-11 min-w-11 items-center justify-center rounded text-secondary hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",onClick:()=>z(t),children:i.jsx(J,{size:18,"aria-hidden":"true"})}):null]},`${t.kind}:${t.id}`),D=(t,u)=>u.length>0?i.jsxs("section",{"aria-label":t,className:"mt-2",children:[i.jsx("h3",{className:"px-2 py-2 text-[13px] font-medium text-secondary",children:t}),u.map(m=>w(m))]}):null,Q=(t,u,m)=>u.length>0?i.jsxs("details",{open:m,className:"mt-2 border-y border-default",children:[i.jsxs("summary",{className:"min-h-11 cursor-pointer px-2 py-3 text-sm text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[t," (",u.length,")"]}),u.map(v=>w(v))]},`${l?.id??"root"}:${t}`):null;return i.jsxs("div",{className:"min-w-0",children:[i.jsx("span",{id:`${a}-label`,className:p==="sr-only"?"sr-only":"mb-1 block text-sm font-medium text-heading",children:d}),i.jsxs("details",{ref:C,className:"relative",onToggle:t=>{t.target===t.currentTarget&&t.currentTarget.open&&I.current?.focus()},onKeyDown:t=>{t.key==="Escape"&&(t.preventDefault(),t.currentTarget.open=!1,t.currentTarget.querySelector("summary")?.focus())},children:[i.jsxs("summary",{id:`${a}-value`,"aria-labelledby":`${a}-label ${a}-value`,className:`${X} visibility-scope-trigger`,onClick:()=>{C.current?.open||ie()},children:[`${E(r)}${r.kind==="group"?` · ${ee(r.targetCount)}`:r.kind==="property"?` · ${s.find(t=>t.kind==="market"&&t.id===c)?.label??(r.marketKeys?.length?q.allMarkets:"Property")}`:r.kind==="market"?" · Market":""}`,i.jsx(de,{size:16,"aria-hidden":"true",className:"shrink-0 text-secondary"})]}),i.jsxs("div",{className:"visibility-scope-menu",children:[l||g?i.jsxs("div",{className:"mb-2 border-b border-default pb-2",children:[i.jsx("button",{type:"button",className:G,"aria-label":`Back to ${F?.label??"all groups"}`,onClick:()=>{k(N.slice(0,-1)),$(!1),b(""),I.current?.focus()},children:i.jsxs("span",{className:"flex items-center gap-1",children:[i.jsx(pe,{size:16,"aria-hidden":"true"}),F?.label??"All groups"]})}),i.jsx("p",{className:"px-2 py-1 text-sm font-medium text-heading","aria-live":"polite",children:l?.label??"All properties"})]}):null,i.jsx("input",{ref:I,type:"search","aria-label":"Search scopes",className:X,placeholder:l?"Search within this group":g?"Search properties":"Search groups or properties",value:f,onChange:t=>b(t.target.value)}),i.jsxs("div",{className:"mt-2 max-h-80 overflow-y-auto",children:[n&&l&&!x?w(l,"All properties in this group"):null,Y.map(t=>w(t)),l&&!x?Q("Subgroups",A,!0):D(l?"Subgroups":"Groups",A),x?D("Properties",V):Q(l&&A.length>0?"All properties":"Properties",V,!l||A.length===0),D("Markets",W),!l&&!g&&!x&&y.length>0&&_.length>0?i.jsxs("button",{type:"button",className:`${G} mt-2 border-t border-default`,"aria-label":q.browseAll,onClick:()=>{$(!0),I.current?.focus()},children:[i.jsx("span",{children:"All properties"}),i.jsx(J,{size:18,"aria-hidden":"true"})]}):null,x&&A.length+V.length+W.length+Y.length===0?i.jsx("p",{className:"py-3 text-sm text-secondary",children:"No matching scopes."}):null]})]})]})]})}function Ee(e){const r=e[0];return r?e.every(o=>o.mode===r.mode&&o.scope.kind===r.scope.kind&&o.scope.key===r.scope.key&&o.queryClass===r.queryClass&&o.measurement.displayedRunId===r.measurement.displayedRunId):!0}function M(e){return e.state==="unavailable"?{numerator:null,denominator:null,reason:e.reason}:e.numerator===void 0||e.denominator===void 0||e.denominator<=0?{numerator:null,denominator:null,reason:"not_applicable"}:{numerator:e.numerator,denominator:e.denominator,...e.unattributed===void 0?{}:{unattributed:e.unattributed},...e.unchecked===void 0?{}:{unchecked:e.unchecked}}}function ye(e){return e.kind==="exact"?e.url:e.kind==="prefix"?`https://${e.host}${e.pathPrefix}/*`:`https://${e.host}/*`}function be(e){return e==="assigned"?"this-property":e==="sibling"?"another-property":e==="ownedUnmapped"?"owned-unassigned":e==="external"?"external":e==="ambiguous"?"multiple-properties":"invalid-url"}function xe(e){return e==="assigned"?"positive":e==="external"?"neutral":e==="invalid"?"negative":"caution"}function te(e){return`target:${e.targetKey}:${e.queryId}:${e.executionNodeKey}`}function ke(e,r,o){const c=new Map;if(!r)return c;const d=new Map(e.usageEdges.map(s=>[te(s),s.targetKey])),p=new Map(e.assignments.map(s=>[`${s.targetKey}:${s.queryId}`,s.queryClass])),n=new Map(e.usageEdges.map(s=>[te(s),p.get(`${s.targetKey}:${s.queryId}`)]));for(const s of r.evidence){if(o&&n.get(s.usageEdgeId)!==o)continue;const f=d.get(s.usageEdgeId);if(!f)continue;const b=c.get(f)??[];b.push({id:`${s.observationId}:${s.expectedSlotId}:${s.usageEdgeId}:${s.sourceUrl}`,kind:be(s.classification),query:s.queryText,provider:s.provider,location:s.location,url:s.sourceUrl,tone:xe(s.classification),historical:s.historical||s.bridged}),c.set(f,b)}return c}function Ce(e){if(e.flags>0)return{label:"Review",tone:"caution"};const r=[e.mentionCoverage,e.citationCoverage].filter(o=>o.state==="unavailable").map(o=>o.reason);return r.includes("no_completed_run")?{label:"Not measured",tone:"neutral"}:r.includes("plan_v1")?{label:"Update setup",tone:"caution"}:r.includes("evidence_incomplete")?{label:"Evidence incomplete",tone:"caution"}:r.includes("identity_ambiguous")?{label:ue.ambiguous,tone:"caution"}:r.includes("no_population")?{label:"No queries",tone:"neutral"}:r.includes("not_applicable")?{label:"Not applicable",tone:"neutral"}:{label:"Complete",tone:"positive"}}function je(e){return e==="complete"?{label:"Complete",tone:"positive"}:e==="partial"?{label:"Partial",tone:"caution"}:e==="queued"?{label:"Queued",tone:"neutral"}:e==="running"?{label:"Running",tone:"neutral"}:e==="failed"?{label:"Failed",tone:"negative"}:{label:"Not measured",tone:"neutral"}}function Ne(e){if(!e)return"";const r=new Date(e);return Number.isFinite(r.getTime())?r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric",timeZone:"UTC"}):""}function re(e){const r=e.nextAction.count??e.flags.total;if(e.nextAction.kind==="review_flags")return`${r} flagged ${r===1?"result needs":"results need"} review.`;if(e.nextAction.kind==="complete_setup")return"Finish setup.";if(e.nextAction.kind==="republish_setup")return"Setup update required.";if(e.nextAction.kind==="run_measurement")return"Ready to measure."}function qe({overview:e,activePlan:r,report:o,reportState:c=o?"ready":"loading",sort:d}){if(r.plan.schemaVersion!==2||e.mode!=="active-v2")throw new Error("The current overview requires an active version-two setup.");if(e.scope.kind!=="all"&&e.scope.kind!=="group")throw new Error("The current overview requires an All Properties or group scope.");const p=r.plan,n=new Map(p.targets.map(a=>[a.stableKey,a])),s=new Map(p.querySnapshots.map(a=>[a.queryId,a.queryText])),f=new Map;for(const a of p.assignments){if(e.queryClass!=="all"&&a.queryClass!==e.queryClass)continue;const y=s.get(a.queryId);if(!y)continue;const h=f.get(a.targetKey)??new Set;h.add(y),f.set(a.targetKey,h)}const b=o?.revision===r.revision&&o.run?.id===e.measurement.displayedRunId?o:null,N=e.measurement.displayedRunId===void 0||b?"ready":c==="error"||o!=null?"error":"loading",k=ke(p,b,e.queryClass==="all"?void 0:e.queryClass),g=new Map;for(const a of p.groups)for(const y of a.targetKeys)g.has(y)||g.set(y,a.label);const $=e.properties.items.map(a=>{const y=n.get(a.targetKey),h=k.get(a.targetKey)??[];return{id:a.targetKey,name:a.label,mentionCoverage:M(a.mentionCoverage),citationCoverage:M(a.citationCoverage),status:Ce(a),providers:a.providers?.map(l=>({provider:l.provider,mentionCoverage:M(l.mentionCoverage),citationCoverage:M(l.citationCoverage)})),market:g.get(a.targetKey),assignedQueries:[...f.get(a.targetKey)??[]],urls:y?.urlMatchers.map(ye)??[],evidence:h,evidenceState:N,historical:h.some(l=>l.historical)}}),C=e.namedShareOfVoice?.entries.map(a=>({name:a.label,coverage:{numerator:a.credits,denominator:e.namedShareOfVoice.denominator}})),I=e.properties.items.flatMap(a=>a.flags>0?[{id:`property:${a.targetKey}`,property:a.label,summary:`${a.flags} ${a.flags===1?"result needs":"results need"} review.`,tone:"caution",count:a.flags}]:[]);return{classReporting:"available",latestMeasurement:{status:je(e.measurement.state),completedSlots:e.measurement.completed,totalSlots:e.measurement.expected,date:Ne(e.measurement.completedAt),includesBridgedHistory:e.measurement.includesHistoricalData===!0},currentView:{scope:e.scope.kind==="group"?{kind:"group",...e.scope.key?{key:e.scope.key}:{}}:{kind:"all"},queryClass:e.queryClass,aggregate:{metrics:{propertiesMentioned:M(e.metrics.propertiesMentioned),mentionCoverage:M(e.metrics.mentionCoverage),citationCoverage:M(e.metrics.citationCoverage)},properties:$,...C?{shareOfVoice:C}:{}},propertyTotal:e.properties.totalEstimate??$.length,outcomes:e.outcomes,nextCursor:e.properties.nextCursor,...d?{sort:d}:{}},availableGroups:p.groups.map(a=>({id:a.stableKey,label:a.label})),...re(e)?{nextActionText:re(e)}:{},flaggedResultsTotal:e.flags.total,flaggedResults:I}}export{Se as A,q as M,Ke as V,Ae as a,Ee as b,qe as c,ye as m};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-DvWWyhGp.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-C2X_UARl.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-ZXXkndVj.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-twS1M3FF.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-D-cUuLZo.js">
@@ -3637,8 +3637,18 @@ var measurementMetricValueSchema = z6.discriminatedUnion("state", [
3637
3637
  * Mention coverage only: answers left out of numerator and denominator
3638
3638
  * because they could not be tied to one Property. Absent means none.
3639
3639
  */
3640
- unattributed: z6.number().int().positive().optional()
3641
- }).strict(),
3640
+ unattributed: z6.number().int().positive().optional(),
3641
+ /**
3642
+ * Citation coverage only: saved answers left out of numerator and
3643
+ * denominator because their source-link capture was incomplete. A link
3644
+ * such an answer did capture is not counted either. Absent means none.
3645
+ */
3646
+ unchecked: z6.number().int().positive().optional()
3647
+ }).strict().superRefine((value, ctx) => {
3648
+ if (value.unattributed !== void 0 && value.unchecked !== void 0) {
3649
+ ctx.addIssue({ code: "custom", path: ["unchecked"], message: "A metric reads one signal: unattributed (mention) and unchecked (citation) cannot share it" });
3650
+ }
3651
+ }),
3642
3652
  z6.object({
3643
3653
  state: z6.literal("unavailable"),
3644
3654
  reason: measurementMetricUnavailableReasonSchema
@@ -8220,7 +8230,22 @@ var visibilityReportRateSchema = z20.object({
8220
8230
  * absent means none were. When every answer is unattributable the rate is
8221
8231
  * unavailable with reason `identity-ambiguous` instead.
8222
8232
  */
8223
- unattributed: z20.number().int().positive().optional()
8233
+ unattributed: z20.number().int().positive().optional(),
8234
+ /**
8235
+ * Saved answers left out of a citation rate because their source-link
8236
+ * capture was incomplete (`citationComplete: false`). They leave the
8237
+ * numerator AND the denominator: a link that was never read is not counted as
8238
+ * not cited, and a link that was read on such an answer is not counted as
8239
+ * cited either, since counting only those positives would bias the rate up.
8240
+ * Present only on an available rate that left at least one answer out;
8241
+ * absent means none were. When every answer is unchecked the rate is
8242
+ * unavailable with reason `evidence-incomplete`, and a missing answer (no
8243
+ * saved observation) still withholds the rate that way. Never beside
8244
+ * `unattributed`: one rate reads one signal. A Simple project's citation
8245
+ * state comes from stored cited domains, not URL capture, so its rates never
8246
+ * carry this field.
8247
+ */
8248
+ unchecked: z20.number().int().positive().optional()
8224
8249
  }).strict().superRefine((value, ctx) => {
8225
8250
  const unavailable = value.numerator === null || value.denominator === null || value.rate === null;
8226
8251
  if (unavailable) {
@@ -8230,11 +8255,17 @@ var visibilityReportRateSchema = z20.object({
8230
8255
  if (value.unattributed !== void 0) {
8231
8256
  ctx.addIssue({ code: z20.ZodIssueCode.custom, path: ["unattributed"], message: "Only an available rate can leave answers out" });
8232
8257
  }
8258
+ if (value.unchecked !== void 0) {
8259
+ ctx.addIssue({ code: z20.ZodIssueCode.custom, path: ["unchecked"], message: "Only an available rate can leave answers out" });
8260
+ }
8233
8261
  return;
8234
8262
  }
8235
8263
  if (value.reason !== void 0) {
8236
8264
  ctx.addIssue({ code: z20.ZodIssueCode.custom, message: "Available rates cannot carry a reason" });
8237
8265
  }
8266
+ if (value.unattributed !== void 0 && value.unchecked !== void 0) {
8267
+ ctx.addIssue({ code: z20.ZodIssueCode.custom, path: ["unchecked"], message: "A rate reads one signal: unattributed (mention) and unchecked (citation) cannot share it" });
8268
+ }
8238
8269
  const { numerator, denominator } = value;
8239
8270
  if (denominator === null || numerator === null) return;
8240
8271
  if (denominator === 0) {
@@ -8885,7 +8916,8 @@ var measurementRateSchema = z22.union([
8885
8916
  numerator: z22.number().int().nonnegative(),
8886
8917
  denominator: z22.number().int().positive(),
8887
8918
  rate: fraction(z22.number().min(0).max(1)),
8888
- unattributed: z22.number().int().positive().optional()
8919
+ unattributed: z22.number().int().positive().optional(),
8920
+ unchecked: z22.number().int().positive().optional()
8889
8921
  }).strict(),
8890
8922
  z22.object({
8891
8923
  numerator: z22.null(),
@@ -8897,6 +8929,9 @@ var measurementRateSchema = z22.union([
8897
8929
  if (value.numerator !== null && value.numerator > value.denominator) {
8898
8930
  ctx.addIssue({ code: "custom", path: ["numerator"], message: "Rate numerator cannot exceed denominator" });
8899
8931
  }
8932
+ if (value.numerator !== null && value.unattributed !== void 0 && value.unchecked !== void 0) {
8933
+ ctx.addIssue({ code: "custom", path: ["unchecked"], message: "A rate reads one signal: unattributed (mention) and unchecked (citation) cannot share it" });
8934
+ }
8900
8935
  });
8901
8936
  var normalizedMeasurementProviderSchema = z22.string().trim().min(1).overwrite((value) => value.toLocaleLowerCase("en"));
8902
8937
  var measurementExpectedSlotV1Schema = z22.object({
@@ -20420,6 +20455,32 @@ function unattributedAnswersLabel(value) {
20420
20455
  if (value.unattributed === void 0 || value.unattributed <= 0) return null;
20421
20456
  return `${value.unattributed} of ${value.denominator + value.unattributed} answers could not be tied to one property`;
20422
20457
  }
20458
+ function uncheckedSourcesLabel(value) {
20459
+ if (value.denominator === null || value.denominator === void 0) return null;
20460
+ if (value.unchecked === void 0 || value.unchecked <= 0) return null;
20461
+ const total = value.denominator + value.unchecked;
20462
+ return `${value.unchecked} of ${total} ${total === 1 ? "answer" : "answers"} had sources that could not be checked`;
20463
+ }
20464
+
20465
+ // ../contracts/src/coverage-rate.ts
20466
+ function assertCount(name, value) {
20467
+ if (!Number.isInteger(value) || value < 0) {
20468
+ throw new RangeError(`${name} must be a non-negative integer, got ${value}`);
20469
+ }
20470
+ }
20471
+ function rateOverChecked(numerator, answers, excluded, field) {
20472
+ assertCount("numerator", numerator);
20473
+ assertCount("answers", answers);
20474
+ assertCount("excluded", excluded);
20475
+ if (excluded > answers) throw new RangeError(`excluded (${excluded}) cannot exceed answers (${answers})`);
20476
+ const denominator = answers - excluded;
20477
+ if (numerator > denominator) {
20478
+ throw new RangeError(`numerator (${numerator}) cannot exceed the ${denominator} checked answers`);
20479
+ }
20480
+ if (denominator === 0) return null;
20481
+ const rate2 = { numerator, denominator, rate: numerator / denominator };
20482
+ return excluded === 0 ? rate2 : { ...rate2, [field]: excluded };
20483
+ }
20423
20484
 
20424
20485
  export {
20425
20486
  __export,
@@ -21374,5 +21435,7 @@ export {
21374
21435
  parseTrafficAnalyticsPeriod,
21375
21436
  trafficAnalyticsResponseSchema,
21376
21437
  UNATTRIBUTED_MENTION_REASON,
21377
- unattributedAnswersLabel
21438
+ unattributedAnswersLabel,
21439
+ uncheckedSourcesLabel,
21440
+ rateOverChecked
21378
21441
  };
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-JU6TPMCJ.js";
8
+ } from "./chunk-JURAGZOO.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -50,7 +50,7 @@ import {
50
50
  skillsClientSchema,
51
51
  upgradeCaveatFor,
52
52
  upgradeCommandFor
53
- } from "./chunk-PXRUWG75.js";
53
+ } from "./chunk-3L7QPB37.js";
54
54
 
55
55
  // src/config.ts
56
56
  import fs from "fs";
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-TNLOOXUP.js";
7
+ } from "./chunk-6Z5MRX24.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
- } from "./chunk-JU6TPMCJ.js";
10
+ } from "./chunk-JURAGZOO.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-PXRUWG75.js";
14
+ } from "./chunk-3L7QPB37.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";
@@ -135,7 +135,7 @@ import {
135
135
  trafficSeriesGranularitySchema,
136
136
  visibilityCompareSelectionSchema,
137
137
  visibilityReportRequestSchema
138
- } from "./chunk-PXRUWG75.js";
138
+ } from "./chunk-3L7QPB37.js";
139
139
 
140
140
  // src/cli-error.ts
141
141
  function isMachineFormat(format) {
@@ -2911,7 +2911,7 @@ var canonryMcpTools = [
2911
2911
  defineTool({
2912
2912
  name: "canonry_measurement_portfolio_summary",
2913
2913
  title: "Summarize measured Properties",
2914
- description: "Start here for best and worst Properties. One call returns the weakest Properties, the names answers wrote instead of them, and the domains engines cited for them. Defaults to non-brand queries; state the returned queryClass and never pool branded with non-brand. Returns at most 4 Property rows per list, the most that fit one result; a larger limit is lowered and limitNote says so. For other rows pass groupKey (one metro's weakest), or page canonry_measurement_overview. Mention (answer text names the Property) and citation (a source URL on its page) are separate: report each as numerator/denominator, with any unattributed count beside mention. Denominators count answers, one per query per engine (queries x engines = answers). Group Properties only by each row's metro and submarkets, never by label. namedInsteadInAnswerText lists names written in the answer text of answers that neither named nor cited the Property, counted by answer: they are not citations, and namedInsteadInAnswerTextTotal counts distinct names, not answers. citedDomains and weakestAnswerSources count answers citing each domain, every engine included; weakestAnswerSources pools the weakest rows plus every tied Property, each answer once, and its domainTotal counts distinct domains, not citations. weakestAnswerSources.ownDomainAnswers counts those answers that cite any of your own domains. A Property's citationCoverage counts only answers citing that Property's own page, so 0% citation does not mean your domain went uncited; use ownDomainAnswers for that. When tiedAtWeakest is set, tiedAtWeakest.count Properties share the weakest rates and the rows are the first of them by name, not a rank: report the count, tiedAtWeakest.byMetro (tied Properties per metro over the whole tie; a Property in two metros counts in both) and tiedAtWeakest.namedInstead (names written instead across the whole tie, counted by distinct answer; namedInsteadTotal is distinct names), and call the rows examples. mentionRanking.strongest/.weakest rank every Property with an available mention rate; .excluded lists the rest with reasons. markets lists every market at one level, worst-first (every metro, or a groupKey's submarkets), whatever the limit. Markets may share Properties and never sum to portfolio totals. Reads stored data only; never starts provider work.",
2914
+ description: "Start here for best and worst Properties. One call returns the weakest Properties, the names answers wrote instead of them, and the domains engines cited for them. Defaults to non-brand queries; state the returned queryClass and never pool branded with non-brand. Returns at most 4 Property rows per list, the most that fit one result; a larger limit is lowered and limitNote says so. For other rows pass groupKey (one metro's weakest), or page canonry_measurement_overview. Mention (answer text names the Property) and citation (a source URL on its page) are separate: report each as numerator/denominator, with any unattributed count beside mention and any unchecked count beside citation (saved answers whose source capture was incomplete; they are in neither side). Denominators count answers, one per query per engine (queries x engines = answers, less any unattributed or unchecked). Group Properties only by each row's metro and submarkets, never by label. namedInsteadInAnswerText lists names written in the answer text of answers that neither named nor cited the Property, counted by answer: they are not citations, and namedInsteadInAnswerTextTotal counts distinct names, not answers. citedDomains and weakestAnswerSources count answers citing each domain, every engine included; weakestAnswerSources pools the weakest rows plus every tied Property, each answer once, and its domainTotal counts distinct domains, not citations. weakestAnswerSources.ownDomainAnswers counts those answers that cite any of your own domains. A Property's citationCoverage counts only answers citing that Property's own page, so 0% citation does not mean your domain went uncited; use ownDomainAnswers for that. When tiedAtWeakest is set, tiedAtWeakest.count Properties share the weakest rates and the rows are the first of them by name, not a rank: report the count, tiedAtWeakest.byMetro (tied Properties per metro over the whole tie; a Property in two metros counts in both) and tiedAtWeakest.namedInstead (names written instead across the whole tie, counted by distinct answer; namedInsteadTotal is distinct names), and call the rows examples. mentionRanking.strongest/.weakest rank every Property with an available mention rate; .excluded lists the rest with reasons. markets lists every market at one level, worst-first (every metro, or a groupKey's submarkets), whatever the limit. Markets may share Properties and never sum to portfolio totals. Reads stored data only; never starts provider work.",
2915
2915
  access: "read",
2916
2916
  tier: "monitoring",
2917
2917
  inputSchema: measurementPortfolioSummaryInputSchema,
@@ -5,7 +5,7 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-SWSWCUHS.js";
8
+ } from "./chunk-ZHI2MCMD.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
@@ -13,7 +13,7 @@ import {
13
13
  TEMPLATE_LINK_RATIO_THRESHOLD,
14
14
  factorStatusFromScore,
15
15
  roundPreservingTotal
16
- } from "./chunk-PXRUWG75.js";
16
+ } from "./chunk-3L7QPB37.js";
17
17
 
18
18
  // src/site-audit-factors.ts
19
19
  function recordedSharePct(factor) {
@@ -20,20 +20,20 @@ import {
20
20
  saveConfig,
21
21
  saveConfigPatch,
22
22
  sentimentInstallReadiness
23
- } from "./chunk-TNLOOXUP.js";
23
+ } from "./chunk-6Z5MRX24.js";
24
24
  import {
25
25
  computeFactorAverages,
26
26
  deleteSiteCrawlGraphLayout,
27
27
  persistSiteCrawlGraphLayout,
28
28
  prepareSiteCrawlGraphLayout,
29
29
  recordedSharePct
30
- } from "./chunk-XFVJ6QVE.js";
30
+ } from "./chunk-KS66E5H6.js";
31
31
  import {
32
32
  CanonryMcpToolNames,
33
33
  CliError,
34
34
  PACKAGE_VERSION,
35
35
  canonryMcpTools
36
- } from "./chunk-JU6TPMCJ.js";
36
+ } from "./chunk-JURAGZOO.js";
37
37
  import {
38
38
  CC_CACHE_DIR,
39
39
  DUCKDB_SPEC,
@@ -205,7 +205,7 @@ import {
205
205
  siteLivenessState,
206
206
  toAlertView,
207
207
  usageCounters
208
- } from "./chunk-SWSWCUHS.js";
208
+ } from "./chunk-ZHI2MCMD.js";
209
209
  import {
210
210
  AGENT_MEMORY_VALUE_MAX_BYTES,
211
211
  AGENT_NONE,
@@ -411,7 +411,7 @@ import {
411
411
  visibilityReportRequestSchema,
412
412
  winnabilityClassLabel,
413
413
  withRetry
414
- } from "./chunk-PXRUWG75.js";
414
+ } from "./chunk-3L7QPB37.js";
415
415
 
416
416
  // src/runtime-context.ts
417
417
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -7869,7 +7869,7 @@ function nonBlank(value) {
7869
7869
  return trimmed ? trimmed : void 0;
7870
7870
  }
7871
7871
  function resolveBuildCommit(env = process.env) {
7872
- const embedded = true ? "ecdc505a5f013390da765689de60fdc18065a2ea" : void 0;
7872
+ const embedded = true ? "1fae609bb90f155eec013fe7e84214c3306cc9b7" : void 0;
7873
7873
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
7874
7874
  }
7875
7875
  function resolveInstanceIdentity(env = process.env) {
@@ -626,6 +626,7 @@ import {
626
626
  queryTrackingWorkspaceResponseSchema,
627
627
  quotaExceeded,
628
628
  rankCriticizedProperties,
629
+ rateOverChecked,
629
630
  recommendationBriefDtoSchema,
630
631
  recommendationExplainRequestSchema,
631
632
  recommendationExplanationDtoSchema,
@@ -795,7 +796,7 @@ import {
795
796
  wordpressSchemaDeployResultDtoSchema,
796
797
  wordpressSchemaStatusResultDtoSchema,
797
798
  wordpressStatusDtoSchema
798
- } from "./chunk-PXRUWG75.js";
799
+ } from "./chunk-3L7QPB37.js";
799
800
 
800
801
  // src/intelligence-service.ts
801
802
  import { eq as eq84, desc as desc37, asc as asc15, and as and71, ne as ne15, or as or20, inArray as inArray33, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists as exists2 } from "drizzle-orm";
@@ -11053,7 +11054,7 @@ function buildRunHistory(runs2, snapshotsByRunId, limit = DEFAULT_RUN_HISTORY_LI
11053
11054
  }
11054
11055
  const totalCount = queryCited.size;
11055
11056
  const citedCount = [...queryCited.values()].filter(Boolean).length;
11056
- const citationRate = percentOf(citedCount, totalCount) ?? 0;
11057
+ const citationRate2 = percentOf(citedCount, totalCount) ?? 0;
11057
11058
  const mentionedCount = [...queryMentioned.values()].filter(Boolean).length;
11058
11059
  const mentionRate3 = percentOf(mentionedCount, totalCount) ?? 0;
11059
11060
  return {
@@ -11061,7 +11062,7 @@ function buildRunHistory(runs2, snapshotsByRunId, limit = DEFAULT_RUN_HISTORY_LI
11061
11062
  createdAt: run.createdAt,
11062
11063
  citedCount,
11063
11064
  totalCount,
11064
- citationRate,
11065
+ citationRate: citationRate2,
11065
11066
  mentionedCount,
11066
11067
  mentionRate: mentionRate3,
11067
11068
  status: run.status
@@ -15731,11 +15732,10 @@ function coverageRate(slots, edges, prepared) {
15731
15732
  if (slots.length === 0) return { numerator: null, denominator: null, rate: null, reason: "no-population" };
15732
15733
  if (!status.complete) return { numerator: null, denominator: null, rate: null, reason: "incomplete" };
15733
15734
  const basis = sourceCompleteSlots(slots, prepared);
15734
- if (basis.length === 0) return { numerator: null, denominator: null, rate: null, reason: "evidence-incomplete" };
15735
15735
  const edgeIds = new Set(edges.map((edge) => edge.id));
15736
15736
  const assignedSlots = new Set(prepared.evidence.filter((row) => edgeIds.has(row.usageEdgeId) && row.classification === "assigned").map((row) => row.expectedSlotId));
15737
15737
  const numerator = basis.filter((slot) => assignedSlots.has(slot.id)).length;
15738
- return { numerator, denominator: basis.length, rate: numerator / basis.length };
15738
+ return rateOverChecked(numerator, slots.length, slots.length - basis.length, "unchecked") ?? unavailable("evidence-incomplete");
15739
15739
  }
15740
15740
  function targetCoverageRate(targetIds, slots, edges, prepared) {
15741
15741
  const status = completeness(slots, prepared);
@@ -15763,9 +15763,7 @@ function mentionRate(target, slots, prepared) {
15763
15763
  return attributableMentionRate(numerator, slots.length, unattributed);
15764
15764
  }
15765
15765
  function attributableMentionRate(numerator, answered2, unattributed) {
15766
- const denominator = answered2 - unattributed;
15767
- if (denominator <= 0) return unavailable("identity-ambiguous");
15768
- return unattributed > 0 ? { numerator, denominator, rate: numerator / denominator, unattributed } : { numerator, denominator, rate: numerator / denominator };
15766
+ return rateOverChecked(numerator, answered2, unattributed, "unattributed") ?? unavailable("identity-ambiguous");
15769
15767
  }
15770
15768
  function providersFor(slots) {
15771
15769
  return sortedUnique(slots.map((slot) => slot.provider));
@@ -15879,11 +15877,13 @@ function buildMeasurementOverviewIndexes(input, prepared, onEvidenceIndexed) {
15879
15877
  slots.push(slot);
15880
15878
  slotsByExecutionId.set(slot.executionId, slots);
15881
15879
  }
15880
+ const observedSlotIds = /* @__PURE__ */ new Set();
15882
15881
  const answeredSlotIds = /* @__PURE__ */ new Set();
15883
15882
  const sourceCompleteSlotIds = /* @__PURE__ */ new Set();
15884
15883
  const mentionedSlotIdsByTargetId = /* @__PURE__ */ new Map();
15885
15884
  const unknownMentionSlotIdsByTargetId = /* @__PURE__ */ new Map();
15886
15885
  for (const [slotId, observation] of prepared.observationsBySlot) {
15886
+ observedSlotIds.add(slotId);
15887
15887
  if (observation.sourceComplete) sourceCompleteSlotIds.add(slotId);
15888
15888
  if (observation.input.answerText === null) continue;
15889
15889
  answeredSlotIds.add(slotId);
@@ -15914,6 +15914,7 @@ function buildMeasurementOverviewIndexes(input, prepared, onEvidenceIndexed) {
15914
15914
  targetsById,
15915
15915
  targetEdgesByTargetId,
15916
15916
  slotsByExecutionId,
15917
+ observedSlotIds,
15917
15918
  answeredSlotIds,
15918
15919
  sourceCompleteSlotIds,
15919
15920
  mentionedSlotIdsByTargetId,
@@ -15968,14 +15969,14 @@ function scopeMentionRate(input, targetIds, slots, answered2, prepared, edges) {
15968
15969
  }
15969
15970
  function indexedScopeCitationRate(slots, edges, indexes) {
15970
15971
  if (slots.length === 0) return unavailable("no-population");
15972
+ if (slots.some((slot) => !indexes.observedSlotIds.has(slot.id))) return unavailable("evidence-incomplete");
15971
15973
  const basis = slots.filter((slot) => indexes.sourceCompleteSlotIds.has(slot.id));
15972
- if (basis.length !== slots.length) return unavailable("evidence-incomplete");
15973
15974
  const assignedSlots = /* @__PURE__ */ new Set();
15974
15975
  for (const edge of edges) {
15975
15976
  for (const slotId of indexes.assignedSlotIdsByEdgeId.get(edge.id) ?? []) assignedSlots.add(slotId);
15976
15977
  }
15977
15978
  const numerator = basis.filter((slot) => assignedSlots.has(slot.id)).length;
15978
- return { numerator, denominator: basis.length, rate: numerator / basis.length };
15979
+ return rateOverChecked(numerator, slots.length, slots.length - basis.length, "unchecked") ?? unavailable("evidence-incomplete");
15979
15980
  }
15980
15981
  function targetMentionRate(targets, slots, answered2, indexes) {
15981
15982
  const mentionable = targets?.filter((target) => target.aliases.some((alias2) => words(alias2).length > 0)) ?? [];
@@ -18416,7 +18417,9 @@ function coverageMetric(rate2) {
18416
18417
  numerator: rate2.numerator,
18417
18418
  denominator: rate2.denominator,
18418
18419
  // Answers the mention rate left out because their identity was unresolved.
18419
- ...rate2.unattributed === void 0 ? {} : { unattributed: rate2.unattributed }
18420
+ ...rate2.unattributed === void 0 ? {} : { unattributed: rate2.unattributed },
18421
+ // Saved answers the citation rate left out because their source capture was incomplete.
18422
+ ...rate2.unchecked === void 0 ? {} : { unchecked: rate2.unchecked }
18420
18423
  };
18421
18424
  }
18422
18425
  function providerRows(property) {
@@ -18580,6 +18583,10 @@ function measurementOutcomeCounts(rows) {
18580
18583
  continue;
18581
18584
  }
18582
18585
  const cited = (citation.numerator ?? citation.value) > 0;
18586
+ if (!cited && citation.unchecked !== void 0) {
18587
+ counts2.notMeasured += 1;
18588
+ continue;
18589
+ }
18583
18590
  if (mentioned && cited) counts2.bothSignals += 1;
18584
18591
  else if (mentioned) counts2.mentionedOnly += 1;
18585
18592
  else if (cited) counts2.citedOnly += 1;
@@ -25496,7 +25503,9 @@ function coverageMetric2(rate2) {
25496
25503
  numerator: rate2.numerator,
25497
25504
  denominator: rate2.denominator,
25498
25505
  // Answers the mention rate left out because their identity was unresolved.
25499
- ...rate2.unattributed === void 0 ? {} : { unattributed: rate2.unattributed }
25506
+ ...rate2.unattributed === void 0 ? {} : { unattributed: rate2.unattributed },
25507
+ // Saved answers the citation rate left out because their source capture was incomplete.
25508
+ ...rate2.unchecked === void 0 ? {} : { unchecked: rate2.unchecked }
25500
25509
  };
25501
25510
  }
25502
25511
  function countMetric2(rate2) {
@@ -25954,15 +25963,15 @@ function weakestTie(ranked) {
25954
25963
  return { summary: null, rows: [] };
25955
25964
  }
25956
25965
  const mentionRate3 = first.mentionCoverage.value;
25957
- const citationRate = first.citationCoverage.value;
25958
- const rows = ranked.filter((row) => row.mentionCoverage.state === "available" && row.mentionCoverage.value === mentionRate3 && row.citationCoverage.state === "available" && row.citationCoverage.value === citationRate);
25966
+ const citationRate2 = first.citationCoverage.value;
25967
+ const rows = ranked.filter((row) => row.mentionCoverage.state === "available" && row.mentionCoverage.value === mentionRate3 && row.citationCoverage.state === "available" && row.citationCoverage.value === citationRate2);
25959
25968
  if (rows.length < 2) return { summary: null, rows: [] };
25960
25969
  const namedInstead = tieNamedInstead(rows);
25961
25970
  return {
25962
25971
  summary: {
25963
25972
  count: rows.length,
25964
25973
  mentionRate: mentionRate3,
25965
- citationRate,
25974
+ citationRate: citationRate2,
25966
25975
  note: MEASUREMENT_PORTFOLIO_TIE_NOTE,
25967
25976
  byMetro: tieByMetro(rows),
25968
25977
  namedInstead: namedInstead.rows,
@@ -26754,8 +26763,27 @@ function targetValues(candidate, targets, targetKey) {
26754
26763
  }
26755
26764
  return { mention: false, citation };
26756
26765
  }
26757
- function citationForCoverage(candidate, targets, targetKey) {
26758
- return candidate.observation?.citationComplete ? targetValues(candidate, targets, targetKey).citation : null;
26766
+ function citationForCoverage(candidate, targets) {
26767
+ return candidate.observation?.citationComplete ? targetValues(candidate, targets).citation : null;
26768
+ }
26769
+ function citationRate(candidates, isCited) {
26770
+ if (candidates.length === 0) return unavailable4("no-population");
26771
+ let numerator = 0;
26772
+ let unchecked = 0;
26773
+ for (const candidate of candidates) {
26774
+ if (candidate.observation === null) return unavailable4("evidence-incomplete");
26775
+ if (!candidate.observation.citationComplete) {
26776
+ unchecked++;
26777
+ continue;
26778
+ }
26779
+ const cited = isCited(candidate);
26780
+ if (cited === null) return unavailable4("evidence-incomplete");
26781
+ if (cited) numerator++;
26782
+ }
26783
+ return rateOverChecked(numerator, candidates.length, unchecked, "unchecked") ?? unavailable4("evidence-incomplete");
26784
+ }
26785
+ function targetCitationRate(candidates, targets, targetKey) {
26786
+ return citationRate(candidates, (candidate) => targetValues(candidate, targets, targetKey).citation);
26759
26787
  }
26760
26788
  function mentionRate2(candidates, targets, targetKey) {
26761
26789
  const values = candidates.map((candidate) => targetValues(candidate, targets, targetKey));
@@ -26769,9 +26797,7 @@ function mentionRate2(candidates, targets, targetKey) {
26769
26797
  unattributed++;
26770
26798
  }
26771
26799
  }
26772
- const denominator = values.length - unattributed;
26773
- if (denominator === 0) return unavailable4("identity-ambiguous");
26774
- return unattributed > 0 ? { numerator, denominator, rate: numerator / denominator, unattributed } : { numerator, denominator, rate: numerator / denominator };
26800
+ return rateOverChecked(numerator, values.length, unattributed, "unattributed") ?? unavailable4("identity-ambiguous");
26775
26801
  }
26776
26802
  function answered(candidate) {
26777
26803
  return candidate.observation !== null;
@@ -26786,16 +26812,18 @@ function targetMetrics(candidates, targets, targetKey) {
26786
26812
  const own = candidates.filter((candidate) => candidate.edges.some((edge) => edge.targetKey === targetKey));
26787
26813
  return {
26788
26814
  mentionCoverage: mentionRate2(own, targets, targetKey),
26789
- citationCoverage: rate(own.map((candidate) => citationForCoverage(candidate, targets, targetKey)), own.length)
26815
+ citationCoverage: targetCitationRate(own, targets, targetKey)
26790
26816
  };
26791
26817
  }
26792
26818
  function targetPresence(candidates, targets, targetKey) {
26793
- const values = candidates.filter((candidate) => candidate.edges.some((edge) => edge.targetKey === targetKey)).map((candidate) => targetValues(candidate, targets, targetKey));
26819
+ const scoped = candidates.filter((candidate) => candidate.edges.some((edge) => edge.targetKey === targetKey));
26820
+ const values = scoped.map((candidate) => targetValues(candidate, targets, targetKey));
26821
+ const citations = scoped.map((candidate, index2) => candidate.observation?.citationComplete === false ? null : values[index2].citation);
26794
26822
  const anyKnown = (signals) => signals.includes(true) ? true : signals.length === 0 || signals.includes(null) ? null : false;
26795
26823
  return {
26796
26824
  targetKey,
26797
26825
  mention: anyKnown(values.map((value) => value.mention)),
26798
- citation: anyKnown(values.map((value) => value.citation)),
26826
+ citation: anyKnown(citations),
26799
26827
  identityAmbiguous: values.some((value) => value.mentionUnavailableReason === "identity-ambiguous")
26800
26828
  };
26801
26829
  }
@@ -26824,7 +26852,7 @@ function coverageSummary(candidates, definition, targets = targetMap(definition)
26824
26852
  queryCount: new Set(rows.map((candidate) => candidate.slot.queryKey)).size,
26825
26853
  answerCount: rows.filter(answered).length,
26826
26854
  mentionCoverage: mentionRate2(rows, targets),
26827
- citationCoverage: rate(rows.map((candidate) => citationForCoverage(candidate, targets)), rows.length)
26855
+ citationCoverage: targetCitationRate(rows, targets)
26828
26856
  };
26829
26857
  }
26830
26858
  function summary2(candidates, definition, populationTargetKeys = selectedTargetKeys(candidates)) {
@@ -26920,15 +26948,12 @@ function competitorRows(candidates) {
26920
26948
  const observation = candidate.observation;
26921
26949
  return observation === null || observation.answerText === null ? null : observation.competitorMentionDomains.includes(domain);
26922
26950
  });
26923
- const citationValues = unique3.map((candidate) => {
26924
- const observation = candidate.observation;
26925
- return observation === null || !observation.citationComplete ? null : observation.competitorCitationDomains.includes(domain);
26926
- });
26927
26951
  return {
26928
26952
  domain,
26929
26953
  answerCount: unique3.filter(answered).length,
26930
26954
  mentionCoverage: rate(mentionValues, unique3.length),
26931
- citationCoverage: rate(citationValues, unique3.length)
26955
+ // The Property rule: an unchecked answer leaves both sides of the rate.
26956
+ citationCoverage: citationRate(unique3, (candidate) => candidate.observation.competitorCitationDomains.includes(domain))
26932
26957
  };
26933
26958
  });
26934
26959
  }
@@ -26968,7 +26993,7 @@ function breakdown(candidates, definition, populationTargetKeys = selectedTarget
26968
26993
  const groupTargetKeys = new Set(targetKeys);
26969
26994
  const own = candidates.map((candidate) => narrowedToTargetKeys(candidate, groupTargetKeys)).filter((candidate) => candidate !== null);
26970
26995
  const metrics = mentionRate2(own, targets);
26971
- const citations = rate(own.map((candidate) => citationForCoverage(candidate, targets)), own.length);
26996
+ const citations = targetCitationRate(own, targets);
26972
26997
  return {
26973
26998
  id: group.id,
26974
26999
  label: group.label,
@@ -27596,6 +27621,8 @@ function frozenSimpleRun(run, definition, snapshots, includeEvidence = true) {
27596
27621
  mentionComplete: snapshot.answerText !== null || snapshot.answerMentioned !== null,
27597
27622
  mentionedTargetKeys: mentioned ? ["project"] : [],
27598
27623
  citedTargetKeys: snapshot.citationState === "cited" ? ["project"] : [],
27624
+ // Simple citation state comes from the stored cited domains, not from
27625
+ // source-URL capture, so a saved Simple answer is never `unchecked`.
27599
27626
  citationComplete: true,
27600
27627
  competitorMentionDomains: competitorSignalsForSnapshot.mentioned,
27601
27628
  competitorCitationDomains: competitorSignalsForSnapshot.cited,
@@ -27678,6 +27705,7 @@ function legacySimpleRun(project, run, snapshots, includeEvidence = true) {
27678
27705
  mentionComplete: snapshot.answerMentioned !== null,
27679
27706
  mentionedTargetKeys: snapshot.answerMentioned === true ? ["project"] : [],
27680
27707
  citedTargetKeys: snapshot.citationState === "cited" ? ["project"] : [],
27708
+ // Legacy rows carry only the stored citation state (see the frozen-simple note).
27681
27709
  citationComplete: true,
27682
27710
  competitorMentionDomains: [],
27683
27711
  competitorCitationDomains: [],