@canonry/canonry 4.172.0 → 4.172.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/assets/assets/{AuditHistoryPanel-DdZeCGyB.js → AuditHistoryPanel-BO_TSFPx.js} +1 -1
  2. package/assets/assets/{BacklinksPage-C3cA1uZG.js → BacklinksPage-CNrzKbiR.js} +1 -1
  3. package/assets/assets/{HistoryPage-ILldZ0uo.js → HistoryPage-CvzLzfj3.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-DdGD-pSU.js → MeasurementPropertyPage-CUdAqft3.js} +1 -1
  5. package/assets/assets/{ProjectPage-BPbmNgA9.js → ProjectPage-xbRWsne7.js} +6 -6
  6. package/assets/assets/{RunRow-BQACorl6.js → RunRow-BLZsQTiY.js} +1 -1
  7. package/assets/assets/{RunsPage-BAt4nfFQ.js → RunsPage-CTuTDUcn.js} +1 -1
  8. package/assets/assets/{SettingsPage-C8jJCoe8.js → SettingsPage-BY-nM5uj.js} +1 -1
  9. package/assets/assets/{SiteHealthSection-K8UY4Jnr.js → SiteHealthSection-br9-ha8G.js} +3 -3
  10. package/assets/assets/{TrafficPage-GuuYfJor.js → TrafficPage-BgX1QlXy.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-BUpxbbyO.js → TrafficSourceDetailPage-D5bsBc6A.js} +1 -1
  12. package/assets/assets/{extract-error-message-DhnfPYL6.js → extract-error-message-BywQFP69.js} +1 -1
  13. package/assets/assets/{index-DgNO-ho5.js → index-BpHZirJJ.js} +2 -2
  14. package/assets/assets/{react-sigma_core.esm.min-B_Td5ND2.js → react-sigma_core.esm.min-Do4rkEBs.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-O226BLC7.js → chunk-3XN226N6.js} +62 -50
  17. package/dist/{chunk-IIFDS3K2.js → chunk-5MRE2TXR.js} +1 -1
  18. package/dist/{chunk-RR4KSDOD.js → chunk-7L4453BU.js} +2 -2
  19. package/dist/{chunk-5KGN224W.js → chunk-IAX4WRAR.js} +4 -4
  20. package/dist/{chunk-HJ7W2LXI.js → chunk-X63CLHYM.js} +11 -0
  21. package/dist/cli.js +41 -18
  22. package/dist/index.js +4 -4
  23. package/dist/{intelligence-service-KT6K4ODY.js → intelligence-service-FSHZXSGK.js} +2 -2
  24. package/dist/mcp.js +3 -3
  25. package/package.json +9 -9
@@ -1,4 +1,4 @@
1
- import{g as Bt,t as S,r as C}from"./vendor-tanstack-Dock0eH1.js";import{e as Ht,G as Wt}from"./SiteHealthSection-K8UY4Jnr.js";import"./index-DgNO-ho5.js";import"./vendor-radix-4UOaVWza.js";import"./vendor-recharts-D8rt5lKn.js";import"./vendor-lucide-nYKv-BB7.js";import"./vendor-markdown-Bn7fRwrx.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-BoYe2M-i.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-Dock0eH1.js";import{e as Ht,G as Wt}from"./SiteHealthSection-br9-ha8G.js";import"./index-BpHZirJJ.js";import"./vendor-radix-4UOaVWza.js";import"./vendor-recharts-D8rt5lKn.js";import"./vendor-lucide-nYKv-BB7.js";import"./vendor-markdown-Bn7fRwrx.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-BoYe2M-i.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
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-DgNO-ho5.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-BpHZirJJ.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dock0eH1.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-4UOaVWza.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-D8rt5lKn.js">
@@ -355,6 +355,7 @@ import {
355
355
  hostMatchesAnyDomain,
356
356
  hostMatchesDomain,
357
357
  hostOf,
358
+ inclusiveDayCount,
358
359
  indexingRequestResponseDtoSchema,
359
360
  internalError,
360
361
  isBrowserProvider,
@@ -624,7 +625,7 @@ import {
624
625
  wordpressSchemaDeployResultDtoSchema,
625
626
  wordpressSchemaStatusResultDtoSchema,
626
627
  wordpressStatusDtoSchema
627
- } from "./chunk-HJ7W2LXI.js";
628
+ } from "./chunk-X63CLHYM.js";
628
629
 
629
630
  // src/intelligence-service.ts
630
631
  import { eq as eq60, desc as desc27, asc as asc11, and as and48, ne as ne8, or as or14, inArray as inArray21, gte as gte14, lte as lte12 } from "drizzle-orm";
@@ -24752,19 +24753,22 @@ function buildGaSection(db, projectId, windowDays2) {
24752
24753
  )
24753
24754
  ).limit(1).get() : void 0;
24754
24755
  const fallbackSummary = windowSummary ? null : db.select().from(gaTrafficSummaries).where(eq28(gaTrafficSummaries.projectId, projectId)).orderBy(desc12(gaTrafficSummaries.syncedAt)).limit(1).get();
24756
+ const matchingFallbackSummary = fallbackSummary && inclusiveDayCount(fallbackSummary.periodStart, fallbackSummary.periodEnd) === windowDays2 ? fallbackSummary : null;
24755
24757
  const snapshotMaxDate = db.select({ m: sql9`MAX(${gaTrafficSnapshots.date})` }).from(gaTrafficSnapshots).where(eq28(gaTrafficSnapshots.projectId, projectId)).get()?.m ?? "";
24756
- if (!windowSummary && !fallbackSummary && !snapshotMaxDate) return null;
24757
- const snapshotStartDate = snapshotMaxDate ? windowStartDate(snapshotMaxDate, windowDays2) : "";
24758
+ if (!windowSummary && !matchingFallbackSummary && !snapshotMaxDate) return null;
24759
+ const summaryPeriod = windowSummary ?? matchingFallbackSummary;
24760
+ const snapshotMaxInWindow = summaryPeriod?.periodEnd || snapshotMaxDate;
24761
+ const snapshotStartDate = summaryPeriod?.periodStart || (snapshotMaxDate ? windowStartDate(snapshotMaxDate, windowDays2) : "");
24758
24762
  const snapshotRows = snapshotStartDate ? db.select().from(gaTrafficSnapshots).where(
24759
24763
  and22(
24760
24764
  eq28(gaTrafficSnapshots.projectId, projectId),
24761
24765
  gte5(gaTrafficSnapshots.date, snapshotStartDate),
24762
- lte3(gaTrafficSnapshots.date, snapshotMaxDate)
24766
+ lte3(gaTrafficSnapshots.date, snapshotMaxInWindow)
24763
24767
  )
24764
24768
  ).all() : db.select().from(gaTrafficSnapshots).where(eq28(gaTrafficSnapshots.projectId, projectId)).all();
24765
- const totalSessions = windowSummary?.totalSessions ?? fallbackSummary?.totalSessions ?? snapshotRows.reduce((s, r) => s + r.sessions, 0);
24766
- const totalUsers = windowSummary?.totalUsers ?? fallbackSummary?.totalUsers ?? snapshotRows.reduce((s, r) => s + r.users, 0);
24767
- const totalOrganicSessions = windowSummary?.totalOrganicSessions ?? fallbackSummary?.totalOrganicSessions ?? snapshotRows.reduce((s, r) => s + r.organicSessions, 0);
24769
+ const totalSessions = windowSummary?.totalSessions ?? matchingFallbackSummary?.totalSessions ?? snapshotRows.reduce((s, r) => s + r.sessions, 0);
24770
+ const totalUsers = windowSummary?.totalUsers ?? matchingFallbackSummary?.totalUsers ?? snapshotRows.reduce((s, r) => s + r.users, 0);
24771
+ const totalOrganicSessions = windowSummary?.totalOrganicSessions ?? matchingFallbackSummary?.totalOrganicSessions ?? snapshotRows.reduce((s, r) => s + r.organicSessions, 0);
24768
24772
  const pageAgg = /* @__PURE__ */ new Map();
24769
24773
  let directSessions = windowSummary?.totalDirectSessions ?? 0;
24770
24774
  for (const r of snapshotRows) {
@@ -24786,9 +24790,9 @@ function buildGaSection(db, projectId, windowDays2) {
24786
24790
  eq28(gaAiReferrals.projectId, projectId),
24787
24791
  eq28(gaAiReferrals.sourceDimension, "session")
24788
24792
  ];
24789
- if (snapshotStartDate && snapshotMaxDate) {
24793
+ if (snapshotStartDate && snapshotMaxInWindow) {
24790
24794
  aiConditions.push(gte5(gaAiReferrals.date, snapshotStartDate));
24791
- aiConditions.push(lte3(gaAiReferrals.date, snapshotMaxDate));
24795
+ aiConditions.push(lte3(gaAiReferrals.date, snapshotMaxInWindow));
24792
24796
  }
24793
24797
  const aiSessionRows = db.select({
24794
24798
  trafficClass: gaAiReferrals.trafficClass,
@@ -24828,8 +24832,8 @@ function buildGaSection(db, projectId, windowDays2) {
24828
24832
  }
24829
24833
  }
24830
24834
  }
24831
- const periodStart = windowSummary?.periodStart ?? (snapshotStartDate || fallbackSummary?.periodStart || "");
24832
- const periodEnd = windowSummary?.periodEnd ?? (snapshotMaxDate || fallbackSummary?.periodEnd || "");
24835
+ const periodStart = snapshotStartDate;
24836
+ const periodEnd = snapshotMaxInWindow;
24833
24837
  return {
24834
24838
  totalSessions,
24835
24839
  totalUsers,
@@ -48195,11 +48199,9 @@ async function ga4Routes(app, opts) {
48195
48199
  requireGa4Connection(opts, project.name, project.canonicalDomain);
48196
48200
  const limit = Math.max(1, Math.min(parseInt(request.query.limit ?? "50", 10) || 50, 500));
48197
48201
  const range = resolveDateRange(request.query);
48198
- const dateFiltered = range.startDate !== null || range.endDate !== null;
48199
- const snapshotConditions = [eq45(gaTrafficSnapshots.projectId, project.id), ...dateRangeConditions(gaTrafficSnapshots.date, range)];
48200
- const aiConditions = [eq45(gaAiReferrals.projectId, project.id), ...dateRangeConditions(gaAiReferrals.date, range)];
48201
- const socialConditions = [eq45(gaSocialReferrals.projectId, project.id), ...dateRangeConditions(gaSocialReferrals.date, range)];
48202
48202
  const windowSummaryRow = range.startDate && !range.explicitDates ? app.db.select({
48203
+ periodStart: gaTrafficWindowSummaries.periodStart,
48204
+ periodEnd: gaTrafficWindowSummaries.periodEnd,
48203
48205
  totalSessions: gaTrafficWindowSummaries.totalSessions,
48204
48206
  totalOrganicSessions: gaTrafficWindowSummaries.totalOrganicSessions,
48205
48207
  totalDirectSessions: gaTrafficWindowSummaries.totalDirectSessions,
@@ -48210,7 +48212,29 @@ async function ga4Routes(app, opts) {
48210
48212
  eq45(gaTrafficWindowSummaries.windowKey, range.window)
48211
48213
  )
48212
48214
  ).get() : null;
48213
- const snapshotTotalsRow = dateFiltered && !windowSummaryRow ? (() => {
48215
+ const projectSummaryRow = app.db.select({
48216
+ periodStart: gaTrafficSummaries.periodStart,
48217
+ periodEnd: gaTrafficSummaries.periodEnd,
48218
+ totalSessions: gaTrafficSummaries.totalSessions,
48219
+ totalOrganicSessions: gaTrafficSummaries.totalOrganicSessions,
48220
+ totalUsers: gaTrafficSummaries.totalUsers
48221
+ }).from(gaTrafficSummaries).where(eq45(gaTrafficSummaries.projectId, project.id)).get();
48222
+ const retainedBounds = [
48223
+ app.db.select({ min: sql17`MIN(${gaTrafficSnapshots.date})`, max: sql17`MAX(${gaTrafficSnapshots.date})` }).from(gaTrafficSnapshots).where(eq45(gaTrafficSnapshots.projectId, project.id)).get(),
48224
+ app.db.select({ min: sql17`MIN(${gaAiReferrals.date})`, max: sql17`MAX(${gaAiReferrals.date})` }).from(gaAiReferrals).where(eq45(gaAiReferrals.projectId, project.id)).get(),
48225
+ app.db.select({ min: sql17`MIN(${gaSocialReferrals.date})`, max: sql17`MAX(${gaSocialReferrals.date})` }).from(gaSocialReferrals).where(eq45(gaSocialReferrals.projectId, project.id)).get()
48226
+ ];
48227
+ const retainedDates = retainedBounds.flatMap((bound) => [bound?.min, bound?.max]).filter((date) => Boolean(date));
48228
+ const projectSummaryCoversAll = Boolean(
48229
+ projectSummaryRow?.periodStart && projectSummaryRow.periodEnd && retainedDates.every((date) => date >= projectSummaryRow.periodStart && date <= projectSummaryRow.periodEnd)
48230
+ );
48231
+ const denominatorRow = windowSummaryRow ?? (range.window === "all" && projectSummaryCoversAll ? projectSummaryRow : null);
48232
+ const denominatorPeriod = denominatorRow?.periodStart && denominatorRow.periodEnd ? { startDate: denominatorRow.periodStart, endDate: denominatorRow.periodEnd } : null;
48233
+ const measuredRange = denominatorPeriod ? { ...range, ...denominatorPeriod } : range;
48234
+ const snapshotConditions = [eq45(gaTrafficSnapshots.projectId, project.id), ...dateRangeConditions(gaTrafficSnapshots.date, measuredRange)];
48235
+ const aiConditions = [eq45(gaAiReferrals.projectId, project.id), ...dateRangeConditions(gaAiReferrals.date, measuredRange)];
48236
+ const socialConditions = [eq45(gaSocialReferrals.projectId, project.id), ...dateRangeConditions(gaSocialReferrals.date, measuredRange)];
48237
+ const snapshotTotalsRow = !denominatorRow ? (() => {
48214
48238
  const summed = app.db.select({
48215
48239
  totalSessions: sql17`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)`,
48216
48240
  totalOrganicSessions: sql17`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)`,
@@ -48219,25 +48243,16 @@ async function ga4Routes(app, opts) {
48219
48243
  return {
48220
48244
  totalSessions: summed?.totalSessions ?? 0,
48221
48245
  totalOrganicSessions: summed?.totalOrganicSessions ?? 0,
48222
- // Unavailable for an EXPLICIT calendar range. The rolling-window
48223
- // fallback keeps its historical summed value: it is wrong for the
48224
- // same reason, but it predates this branch and correcting it is a
48225
- // separate, visible behaviour change rather than one bundled here.
48226
- totalUsers: range.explicitDates ? null : summed?.totalUsers ?? 0
48246
+ // Unavailable for an explicit or all-history range. The rolling-
48247
+ // window fallback keeps its historical summed value for projects
48248
+ // that have not yet backfilled window summaries.
48249
+ totalUsers: range.explicitDates || range.window === "all" ? null : summed?.totalUsers ?? 0
48227
48250
  };
48228
48251
  })() : null;
48229
- const summaryRow = dateFiltered ? windowSummaryRow ?? snapshotTotalsRow : app.db.select({
48230
- totalSessions: gaTrafficSummaries.totalSessions,
48231
- totalOrganicSessions: gaTrafficSummaries.totalOrganicSessions,
48232
- totalUsers: gaTrafficSummaries.totalUsers
48233
- }).from(gaTrafficSummaries).where(eq45(gaTrafficSummaries.projectId, project.id)).get();
48252
+ const summaryRow = denominatorRow ?? snapshotTotalsRow;
48234
48253
  const directTotalRow = windowSummaryRow ? { totalDirectSessions: windowSummaryRow.totalDirectSessions } : app.db.select({
48235
48254
  totalDirectSessions: sql17`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)`
48236
48255
  }).from(gaTrafficSnapshots).where(and36(...snapshotConditions)).get();
48237
- const summaryMeta = app.db.select({
48238
- periodStart: gaTrafficSummaries.periodStart,
48239
- periodEnd: gaTrafficSummaries.periodEnd
48240
- }).from(gaTrafficSummaries).where(eq45(gaTrafficSummaries.projectId, project.id)).get();
48241
48256
  const rows = app.db.select({
48242
48257
  landingPage: sql17`COALESCE(${gaTrafficSnapshots.landingPageNormalized}, ${gaTrafficSnapshots.landingPage})`,
48243
48258
  sessions: sql17`SUM(${gaTrafficSnapshots.sessions})`,
@@ -48300,6 +48315,9 @@ async function ga4Routes(app, opts) {
48300
48315
  const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
48301
48316
  const totalOrganicSessions = summaryRow?.totalOrganicSessions ?? 0;
48302
48317
  const socialSessions = socialTotals?.sessions ?? 0;
48318
+ const windowStart = measuredRange.startDate;
48319
+ const windowEnd = measuredRange.endDate;
48320
+ const windowDays2 = windowStart && windowEnd ? inclusiveDayCount(windowStart, windowEnd) : null;
48303
48321
  const channelBreakdown = buildChannelBreakdown({
48304
48322
  totalSessions: total,
48305
48323
  organicSessions: totalOrganicSessions,
@@ -48315,7 +48333,7 @@ async function ga4Routes(app, opts) {
48315
48333
  // it. GA counts users as a COUNT DISTINCT at the grain requested, so the
48316
48334
  // landing-page dimensioned sum is inflated, and a 0 would read as
48317
48335
  // "nobody visited" rather than "not measurable for this range".
48318
- totalUsers: summaryRow ? summaryRow.totalUsers : 0,
48336
+ totalUsers: summaryRow ? summaryRow.totalUsers : null,
48319
48337
  topPages: rows.map((r) => ({
48320
48338
  landingPage: r.landingPage,
48321
48339
  sessions: r.sessions ?? 0,
@@ -48382,25 +48400,19 @@ async function ga4Routes(app, opts) {
48382
48400
  directSharePctDisplay: formatSharePct(totalDirectSessions, total),
48383
48401
  socialSharePctDisplay: formatSharePct(socialSessions, total),
48384
48402
  lastSyncedAt: latestSync?.syncedAt ?? null,
48385
- // Report the range that was actually measured, so a caller can tell which
48386
- // period the totals above belong to.
48387
- // An EXPLICIT calendar range is reported back verbatim, even when it
48388
- // covers nothing. Substituting the synced period there labelled an empty
48389
- // future range with real past dates, so the numbers said "no data" while
48390
- // the labels named a period that did have data.
48391
- //
48392
- // A rolling window still clamps: "last 30 days" is a relative ask, and a
48393
- // cutoff computed from today can legitimately land after the last synced
48394
- // date on a stale project. Reporting a start after the end would be its
48395
- // own nonsense.
48396
- periodStart: (() => {
48397
- if (range.explicitDates) return range.startDate ?? summaryMeta?.periodStart ?? null;
48398
- const start = range.startDate ?? summaryMeta?.periodStart ?? null;
48399
- const end = range.endDate ?? summaryMeta?.periodEnd ?? null;
48400
- if (start && end && start > end) return summaryMeta?.periodStart ?? null;
48401
- return start;
48402
- })(),
48403
- periodEnd: range.endDate ?? summaryMeta?.periodEnd ?? null
48403
+ // The window every figure above was measured over never a different
48404
+ // table's period, and never a fallback that names dates the queries did
48405
+ // not use. A `null` bound is genuinely open (all retained history on that
48406
+ // side), which is why `windowDays` is null too rather than guessing a
48407
+ // span. Read a share against these dates or not at all.
48408
+ windowStart,
48409
+ windowEnd,
48410
+ windowDays: windowDays2,
48411
+ // Retained aliases of `windowStart` / `windowEnd`. They previously mixed
48412
+ // the requested range with the synced range, which is what let a 30-day
48413
+ // total sit under a 90-day channel count with a label that named neither.
48414
+ periodStart: windowStart,
48415
+ periodEnd: windowEnd
48404
48416
  };
48405
48417
  });
48406
48418
  app.get("/projects/:name/ga/ai-referral-history", async (request, _reply) => {
@@ -91,7 +91,7 @@ import {
91
91
  trafficConnectWordpressRequestSchema,
92
92
  trafficEventKindSchema,
93
93
  trafficSeriesGranularitySchema
94
- } from "./chunk-HJ7W2LXI.js";
94
+ } from "./chunk-X63CLHYM.js";
95
95
 
96
96
  // src/config.ts
97
97
  import fs from "fs";
@@ -5,11 +5,11 @@ import {
5
5
  installSkills,
6
6
  loadConfigRaw,
7
7
  saveConfigPatch
8
- } from "./chunk-IIFDS3K2.js";
8
+ } from "./chunk-5MRE2TXR.js";
9
9
  import {
10
10
  SKILL_MANIFEST_FILENAME,
11
11
  SkillsClients
12
- } from "./chunk-HJ7W2LXI.js";
12
+ } from "./chunk-X63CLHYM.js";
13
13
 
14
14
  // src/skills-autosync.ts
15
15
  import fs from "fs";
@@ -9,7 +9,7 @@ import {
9
9
  loadConfig,
10
10
  loadConfigRaw,
11
11
  saveConfigPatch
12
- } from "./chunk-IIFDS3K2.js";
12
+ } from "./chunk-5MRE2TXR.js";
13
13
  import {
14
14
  CC_CACHE_DIR,
15
15
  DUCKDB_SPEC,
@@ -145,7 +145,7 @@ import {
145
145
  siteCrawlSnapshots,
146
146
  toAlertView,
147
147
  usageCounters
148
- } from "./chunk-O226BLC7.js";
148
+ } from "./chunk-3XN226N6.js";
149
149
  import {
150
150
  AGENT_MEMORY_VALUE_MAX_BYTES,
151
151
  AGENT_PROVIDER_IDS,
@@ -282,7 +282,7 @@ import {
282
282
  validationError,
283
283
  winnabilityClassLabel,
284
284
  withRetry
285
- } from "./chunk-HJ7W2LXI.js";
285
+ } from "./chunk-X63CLHYM.js";
286
286
 
287
287
  // src/telemetry.ts
288
288
  import crypto from "crypto";
@@ -11829,7 +11829,7 @@ function readStoredGroundingSources(rawResponse) {
11829
11829
  return result;
11830
11830
  }
11831
11831
  async function backfillInsightsCommand(project, opts) {
11832
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-KT6K4ODY.js");
11832
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-FSHZXSGK.js");
11833
11833
  const config = loadConfig();
11834
11834
  const db = createClient(config.database);
11835
11835
  migrate(db);
@@ -7078,6 +7078,16 @@ function calendarDateRange(startDate, endDate, cap = 800) {
7078
7078
  }
7079
7079
  return dates;
7080
7080
  }
7081
+ function inclusiveDayCount(startDate, endDate) {
7082
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(startDate) || !/^\d{4}-\d{2}-\d{2}$/.test(endDate)) return null;
7083
+ const startMs = Date.parse(`${startDate}T00:00:00.000Z`);
7084
+ const endMs = Date.parse(`${endDate}T00:00:00.000Z`);
7085
+ if (Number.isNaN(startMs) || Number.isNaN(endMs)) return null;
7086
+ if (new Date(startMs).toISOString().slice(0, 10) !== startDate) return null;
7087
+ if (new Date(endMs).toISOString().slice(0, 10) !== endDate) return null;
7088
+ if (endMs < startMs) return null;
7089
+ return Math.round((endMs - startMs) / 864e5) + 1;
7090
+ }
7081
7091
  function shiftIsoCalendarDate(isoDate, days) {
7082
7092
  if (!Number.isFinite(days)) return isoDate;
7083
7093
  const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate);
@@ -16160,6 +16170,7 @@ export {
16160
16170
  formatIsoDate,
16161
16171
  formatIsoDateInTimeZone,
16162
16172
  calendarDateRange,
16173
+ inclusiveDayCount,
16163
16174
  shiftIsoCalendarDate,
16164
16175
  isoDateDaysBeforeInTimeZone,
16165
16176
  startOfDayHourInTimeZone,
package/dist/cli.js CHANGED
@@ -26,11 +26,11 @@ import {
26
26
  showFirstRunNotice,
27
27
  trackCliCommandFinished,
28
28
  trackEvent
29
- } from "./chunk-5KGN224W.js";
29
+ } from "./chunk-IAX4WRAR.js";
30
30
  import {
31
31
  autoSyncSkills,
32
32
  formatAutoSyncNotice
33
- } from "./chunk-RR4KSDOD.js";
33
+ } from "./chunk-7L4453BU.js";
34
34
  import {
35
35
  CliError,
36
36
  EXIT_SYSTEM_ERROR,
@@ -55,7 +55,7 @@ import {
55
55
  saveConfigPatch,
56
56
  systemError,
57
57
  usageError
58
- } from "./chunk-IIFDS3K2.js";
58
+ } from "./chunk-5MRE2TXR.js";
59
59
  import {
60
60
  CLOUDFLARE_WORKER_BINDINGS,
61
61
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -69,7 +69,7 @@ import {
69
69
  projects,
70
70
  queries,
71
71
  renderReportHtml
72
- } from "./chunk-O226BLC7.js";
72
+ } from "./chunk-3XN226N6.js";
73
73
  import {
74
74
  AdsDeliverySnapshotStatuses,
75
75
  AdsHistoricalCampaignRollupStatuses,
@@ -137,7 +137,7 @@ import {
137
137
  providerQuotaPolicySchema,
138
138
  resolveProviderInput,
139
139
  winnabilityClassSchema
140
- } from "./chunk-HJ7W2LXI.js";
140
+ } from "./chunk-X63CLHYM.js";
141
141
 
142
142
  // src/cli.ts
143
143
  import { pathToFileURL } from "url";
@@ -4019,7 +4019,7 @@ async function gaTraffic(project, opts) {
4019
4019
  `);
4020
4020
  console.log(` Total Sessions: ${result.totalSessions}`);
4021
4021
  console.log(` Organic Sessions: ${result.totalOrganicSessions}`);
4022
- console.log(` Total Users: ${result.totalUsers}`);
4022
+ console.log(` Total Users: ${result.totalUsers ?? "unavailable for this range"}`);
4023
4023
  if (result.aiSessionsDeduped > 0) {
4024
4024
  const share = result.totalSessions > 0 ? Math.round(result.aiSessionsDeduped / result.totalSessions * 100) : 0;
4025
4025
  console.log(` AI Sessions (deduped): ${result.aiSessionsDeduped} (${share}% of total)`);
@@ -4276,6 +4276,11 @@ async function gaCoverage(project, format) {
4276
4276
  );
4277
4277
  }
4278
4278
  }
4279
+ function windowLine(traffic) {
4280
+ if (!traffic.windowStart || !traffic.windowEnd) return null;
4281
+ const span = traffic.windowDays === null ? "" : ` (${traffic.windowDays} days)`;
4282
+ return ` Window: ${traffic.windowStart} to ${traffic.windowEnd}${span}`;
4283
+ }
4279
4284
  async function gaSocialReferralSummary(project, opts) {
4280
4285
  const client = getClient7();
4281
4286
  const traffic = await client.gaTraffic(project);
@@ -4287,12 +4292,18 @@ async function gaSocialReferralSummary(project, opts) {
4287
4292
  socialUsers: traffic.socialUsers,
4288
4293
  totalSessions: traffic.totalSessions,
4289
4294
  socialSharePct: traffic.socialSharePct,
4295
+ windowStart: traffic.windowStart,
4296
+ windowEnd: traffic.windowEnd,
4297
+ windowDays: traffic.windowDays,
4290
4298
  topSources: traffic.socialReferrals.slice(0, 5).map((r) => ({ source: r.source, sessions: r.sessions, channel: r.channelGroup })),
4291
4299
  trend
4292
4300
  }, null, 2));
4293
4301
  return;
4294
4302
  }
4295
4303
  console.log(`Social Traffic Summary for "${project}"
4304
+ `);
4305
+ const trendWindow = windowLine(traffic);
4306
+ if (trendWindow) console.log(`${trendWindow}
4296
4307
  `);
4297
4308
  console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
4298
4309
  console.log(` Users: ${traffic.socialUsers}`);
@@ -4320,11 +4331,17 @@ async function gaSocialReferralSummary(project, opts) {
4320
4331
  socialUsers: traffic.socialUsers,
4321
4332
  totalSessions: traffic.totalSessions,
4322
4333
  socialSharePct: traffic.socialSharePct,
4334
+ windowStart: traffic.windowStart,
4335
+ windowEnd: traffic.windowEnd,
4336
+ windowDays: traffic.windowDays,
4323
4337
  topSources: traffic.socialReferrals.slice(0, 5).map((r) => ({ source: r.source, sessions: r.sessions, channel: r.channelGroup }))
4324
4338
  }, null, 2));
4325
4339
  return;
4326
4340
  }
4327
4341
  console.log(`Social Traffic Summary for "${project}"
4342
+ `);
4343
+ const socialWindow = windowLine(traffic);
4344
+ if (socialWindow) console.log(`${socialWindow}
4328
4345
  `);
4329
4346
  console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
4330
4347
  console.log(` Users: ${traffic.socialUsers}`);
@@ -4382,6 +4399,9 @@ async function gaAttribution(project, opts) {
4382
4399
  aiReferrals: traffic.aiReferrals,
4383
4400
  aiReferralLandingPages: traffic.aiReferralLandingPages,
4384
4401
  socialReferrals: traffic.socialReferrals,
4402
+ windowStart: traffic.windowStart,
4403
+ windowEnd: traffic.windowEnd,
4404
+ windowDays: traffic.windowDays,
4385
4405
  trend
4386
4406
  }, null, 2));
4387
4407
  return;
@@ -4391,9 +4411,12 @@ async function gaAttribution(project, opts) {
4391
4411
  return;
4392
4412
  }
4393
4413
  console.log(`GA4 Attribution Overview for "${project}"
4414
+ `);
4415
+ const trendWindow = windowLine(traffic);
4416
+ if (trendWindow) console.log(`${trendWindow}
4394
4417
  `);
4395
4418
  console.log(` Total Sessions: ${traffic.totalSessions}`);
4396
- console.log(` Total Users: ${traffic.totalUsers}`);
4419
+ console.log(` Total Users: ${traffic.totalUsers ?? "unavailable for this range"}`);
4397
4420
  console.log();
4398
4421
  console.log(" CHANNEL BREAKDOWN 7d trend 30d trend");
4399
4422
  console.log(` Organic Search: ${String(traffic.channelBreakdown.organic.sessions).padEnd(6)} (${traffic.channelBreakdown.organic.sharePctDisplay.padStart(4)}) ${fmtTrend(trend.organic.trend7dPct).padEnd(12)} ${fmtTrend(trend.organic.trend30dPct)}`);
@@ -4415,12 +4438,9 @@ async function gaAttribution(project, opts) {
4415
4438
  const m = trend.socialBiggestMover;
4416
4439
  console.log(` Social Mover: ${m.source} (${m.changePct >= 0 ? "+" : ""}${m.changePct}%, ${m.sessionsPrev7d}\u2192${m.sessions7d} sessions/7d)`);
4417
4440
  }
4418
- if (traffic.periodStart && traffic.periodEnd) {
4419
- console.log(`
4420
- Period: ${traffic.periodStart} to ${traffic.periodEnd}`);
4421
- }
4422
4441
  if (traffic.lastSyncedAt) {
4423
- console.log(` Last synced: ${traffic.lastSyncedAt}`);
4442
+ console.log(`
4443
+ Last synced: ${traffic.lastSyncedAt}`);
4424
4444
  }
4425
4445
  return;
4426
4446
  }
@@ -4463,6 +4483,9 @@ async function gaAttribution(project, opts) {
4463
4483
  aiReferrals: traffic.aiReferrals,
4464
4484
  aiReferralLandingPages: traffic.aiReferralLandingPages,
4465
4485
  socialReferrals: traffic.socialReferrals,
4486
+ windowStart: traffic.windowStart,
4487
+ windowEnd: traffic.windowEnd,
4488
+ windowDays: traffic.windowDays,
4466
4489
  periodStart: traffic.periodStart,
4467
4490
  periodEnd: traffic.periodEnd
4468
4491
  }, null, 2));
@@ -4473,9 +4496,12 @@ async function gaAttribution(project, opts) {
4473
4496
  return;
4474
4497
  }
4475
4498
  console.log(`GA4 Attribution Overview for "${project}"
4499
+ `);
4500
+ const attributionWindow = windowLine(traffic);
4501
+ if (attributionWindow) console.log(`${attributionWindow}
4476
4502
  `);
4477
4503
  console.log(` Total Sessions: ${traffic.totalSessions}`);
4478
- console.log(` Total Users: ${traffic.totalUsers}`);
4504
+ console.log(` Total Users: ${traffic.totalUsers ?? "unavailable for this range"}`);
4479
4505
  console.log();
4480
4506
  console.log(" CHANNEL BREAKDOWN");
4481
4507
  console.log(` Organic Search: ${traffic.channelBreakdown.organic.sessions} sessions (${traffic.channelBreakdown.organic.sharePctDisplay})`);
@@ -4513,12 +4539,9 @@ async function gaAttribution(project, opts) {
4513
4539
  console.log(` ${ref.source.padEnd(25)} ${String(ref.sessions).padEnd(8)} sessions (${chanLabel})`);
4514
4540
  }
4515
4541
  }
4516
- if (traffic.periodStart && traffic.periodEnd) {
4517
- console.log(`
4518
- Period: ${traffic.periodStart} to ${traffic.periodEnd}`);
4519
- }
4520
4542
  if (traffic.lastSyncedAt) {
4521
- console.log(` Last synced: ${traffic.lastSyncedAt}`);
4543
+ console.log(`
4544
+ Last synced: ${traffic.lastSyncedAt}`);
4522
4545
  }
4523
4546
  }
4524
4547
 
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-5KGN224W.js";
6
+ } from "./chunk-IAX4WRAR.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-IIFDS3K2.js";
10
- import "./chunk-O226BLC7.js";
11
- import "./chunk-HJ7W2LXI.js";
9
+ } from "./chunk-5MRE2TXR.js";
10
+ import "./chunk-3XN226N6.js";
11
+ import "./chunk-X63CLHYM.js";
12
12
  export {
13
13
  GoogleMarketingRuntimeError,
14
14
  createGoogleMarketingCredentialStore,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-O226BLC7.js";
4
- import "./chunk-HJ7W2LXI.js";
3
+ } from "./chunk-3XN226N6.js";
4
+ import "./chunk-X63CLHYM.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-RR4KSDOD.js";
3
+ } from "./chunk-7L4453BU.js";
4
4
  import {
5
5
  CliError,
6
6
  PACKAGE_VERSION,
7
7
  canonryMcpTools,
8
8
  createApiClient
9
- } from "./chunk-IIFDS3K2.js";
9
+ } from "./chunk-5MRE2TXR.js";
10
10
  import {
11
11
  isReadOnlyKey
12
- } from "./chunk-HJ7W2LXI.js";
12
+ } from "./chunk-X63CLHYM.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "4.172.0",
3
+ "version": "4.172.1",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -71,29 +71,29 @@
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
73
  "@ainyc/canonry-api-client": "0.0.0",
74
- "@ainyc/canonry-api-routes": "0.0.0",
75
74
  "@ainyc/canonry-config": "0.0.0",
76
- "@ainyc/canonry-db": "0.0.0",
77
75
  "@ainyc/canonry-contracts": "0.0.0",
78
76
  "@ainyc/canonry-integration-bing": "0.0.0",
79
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
80
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
77
+ "@ainyc/canonry-db": "0.0.0",
81
78
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
82
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
83
79
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
80
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
81
+ "@ainyc/canonry-api-routes": "0.0.0",
82
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
84
83
  "@ainyc/canonry-integration-google-ads": "0.0.0",
85
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
86
- "@ainyc/canonry-integration-google": "0.0.0",
84
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
87
85
  "@ainyc/canonry-integration-google-places": "0.0.0",
86
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
88
87
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
89
88
  "@ainyc/canonry-integration-traffic": "0.0.0",
90
89
  "@ainyc/canonry-integration-wordpress": "0.0.0",
91
90
  "@ainyc/canonry-intelligence": "0.0.0",
92
91
  "@ainyc/canonry-provider-cdp": "0.0.0",
93
- "@ainyc/canonry-provider-gemini": "0.0.0",
94
92
  "@ainyc/canonry-provider-local": "0.0.0",
93
+ "@ainyc/canonry-integration-google": "0.0.0",
95
94
  "@ainyc/canonry-provider-openai": "0.0.0",
96
95
  "@ainyc/canonry-provider-perplexity": "0.0.0",
96
+ "@ainyc/canonry-provider-gemini": "0.0.0",
97
97
  "@ainyc/canonry-provider-claude": "0.0.0"
98
98
  },
99
99
  "scripts": {