@sanity/ailf-studio 1.12.1 → 1.14.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 (3) hide show
  1. package/dist/index.d.ts +15 -2
  2. package/dist/index.js +1434 -444
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3534,18 +3534,18 @@ import { route } from "sanity/router";
3534
3534
  // src/components/Dashboard.tsx
3535
3535
  import { HelpCircleIcon as HelpCircleIcon8 } from "@sanity/icons";
3536
3536
  import {
3537
- Box as Box34,
3538
- Button as Button13,
3537
+ Box as Box37,
3538
+ Button as Button15,
3539
3539
  Container,
3540
- Flex as Flex37,
3541
- Stack as Stack40,
3540
+ Flex as Flex39,
3541
+ Stack as Stack42,
3542
3542
  Tab as Tab3,
3543
3543
  TabList as TabList3,
3544
3544
  TabPanel as TabPanel3,
3545
- Text as Text51
3545
+ Text as Text53
3546
3546
  } from "@sanity/ui";
3547
- import { useCallback as useCallback39, useEffect as useEffect17 } from "react";
3548
- import { useRouter as useRouter4 } from "sanity/router";
3547
+ import { useCallback as useCallback43, useEffect as useEffect18 } from "react";
3548
+ import { useRouter as useRouter5 } from "sanity/router";
3549
3549
 
3550
3550
  // src/lib/help-context.ts
3551
3551
  import {
@@ -4225,9 +4225,12 @@ var scoreTimelineQuery = (
4225
4225
  && completedAt >= $startDate
4226
4226
  ${filterSourceClause("$source")}
4227
4227
  ${filterModeClause("$mode")}
4228
+ ${filterOwnerTeamClause("$ownerTeam")}
4228
4229
  ] | order(completedAt asc) {
4229
4230
  _id,
4231
+ reportId,
4230
4232
  completedAt,
4233
+ durationMs,
4231
4234
  "overall": summary.overall.avgScore,
4232
4235
  "scores": summary.scores[] {
4233
4236
  feature,
@@ -4237,6 +4240,10 @@ var scoreTimelineQuery = (
4237
4240
  "actualScore": summary.overall.avgActualScore,
4238
4241
  "mode": provenance.mode,
4239
4242
  "source": provenance.source.name,
4243
+ "trigger": provenance.trigger.type,
4244
+ "areas": provenance.areas,
4245
+ "models": provenance.models[].label,
4246
+ "ownerTeam": provenance.owner.team,
4240
4247
  tag,
4241
4248
  title
4242
4249
  }
@@ -6774,7 +6781,7 @@ import {
6774
6781
  Tooltip as Tooltip10
6775
6782
  } from "@sanity/ui";
6776
6783
  import {
6777
- useCallback as useCallback36,
6784
+ useCallback as useCallback37,
6778
6785
  useEffect as useEffect13,
6779
6786
  useMemo as useMemo16,
6780
6787
  useState as useState27
@@ -10729,7 +10736,7 @@ function JudgmentActions({ onShowPrompts } = {}) {
10729
10736
  // src/components/report-detail/report-actions/ReportActions.tsx
10730
10737
  import { CopyIcon as CopyIcon3 } from "@sanity/icons";
10731
10738
  import { MenuDivider as MenuDivider3, useToast as useToast9 } from "@sanity/ui";
10732
- import { useCallback as useCallback32, useState as useState24 } from "react";
10739
+ import { useCallback as useCallback33, useState as useState24 } from "react";
10733
10740
  import { useClient as useClient11 } from "sanity";
10734
10741
 
10735
10742
  // src/components/report-detail/report-actions/CopyReportAction.tsx
@@ -11083,9 +11090,62 @@ function RerunEvaluationAction({
11083
11090
  );
11084
11091
  }
11085
11092
 
11093
+ // src/components/report-detail/report-actions/ViewArtifactsAction.tsx
11094
+ import { LaunchIcon } from "@sanity/icons";
11095
+ import { MenuItem as MenuItem9 } from "@sanity/ui";
11096
+ import { useCallback as useCallback32 } from "react";
11097
+ import { jsx as jsx50 } from "react/jsx-runtime";
11098
+ function commonPathPrefix(paths) {
11099
+ if (paths.length === 0) return "";
11100
+ const segmented = paths.map((p) => p.split("/").filter(Boolean));
11101
+ if (segmented.length === 1) {
11102
+ const segs = segmented[0];
11103
+ const last = segs.at(-1) ?? "";
11104
+ return (last.includes(".") ? segs.slice(0, -1) : segs).join("/");
11105
+ }
11106
+ const min = Math.min(...segmented.map((s) => s.length));
11107
+ const common = [];
11108
+ for (let i = 0; i < min; i++) {
11109
+ const seg = segmented[0][i];
11110
+ if (segmented.every((s) => s[i] === seg)) common.push(seg);
11111
+ else break;
11112
+ }
11113
+ return common.join("/");
11114
+ }
11115
+ function buildArtifactBrowseUrl(manifest) {
11116
+ if (!manifest) return null;
11117
+ const refs = Object.values(manifest).filter(
11118
+ (ref) => ref?.store === "gcs" && Boolean(ref.bucket)
11119
+ );
11120
+ if (refs.length === 0) return null;
11121
+ const owned = refs.filter((r) => !r.sourceRunId);
11122
+ const usable = owned.length > 0 ? owned : refs;
11123
+ const bucket = usable[0].bucket;
11124
+ const sameBucket = usable.filter((r) => r.bucket === bucket);
11125
+ const prefix = commonPathPrefix(sameBucket.map((r) => r.path));
11126
+ const base = `https://console.cloud.google.com/storage/browser/${encodeURIComponent(bucket)}`;
11127
+ return prefix ? `${base}/${prefix.split("/").map(encodeURIComponent).join("/")}` : base;
11128
+ }
11129
+ function ViewArtifactsAction({ manifest }) {
11130
+ const url = buildArtifactBrowseUrl(manifest);
11131
+ const handleClick = useCallback32(() => {
11132
+ if (url) window.open(url, "_blank", "noopener,noreferrer");
11133
+ }, [url]);
11134
+ if (!url) return null;
11135
+ return /* @__PURE__ */ jsx50(
11136
+ MenuItem9,
11137
+ {
11138
+ icon: LaunchIcon,
11139
+ onClick: handleClick,
11140
+ text: "View run artifacts"
11141
+ }
11142
+ );
11143
+ }
11144
+
11086
11145
  // src/components/report-detail/report-actions/ReportActions.tsx
11087
- import { Fragment as Fragment13, jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
11146
+ import { Fragment as Fragment13, jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
11088
11147
  function ReportActions({
11148
+ artifactManifest,
11089
11149
  documentId,
11090
11150
  onDeleted,
11091
11151
  provenance,
@@ -11093,7 +11153,7 @@ function ReportActions({
11093
11153
  }) {
11094
11154
  const client = useClient11({ apiVersion: API_VERSION });
11095
11155
  const toast = useToast9();
11096
- const handleCopyId = useCallback32(() => {
11156
+ const handleCopyId = useCallback33(() => {
11097
11157
  navigator.clipboard.writeText(reportId).then(
11098
11158
  () => {
11099
11159
  toast.push({
@@ -11113,13 +11173,13 @@ function ReportActions({
11113
11173
  }, [reportId, toast]);
11114
11174
  const [deleteDialogOpen, setDeleteDialogOpen] = useState24(false);
11115
11175
  const [deleting, setDeleting] = useState24(false);
11116
- const handleRequestDelete = useCallback32(() => {
11176
+ const handleRequestDelete = useCallback33(() => {
11117
11177
  setDeleteDialogOpen(true);
11118
11178
  }, []);
11119
- const handleDeleteClose = useCallback32(() => {
11179
+ const handleDeleteClose = useCallback33(() => {
11120
11180
  if (!deleting) setDeleteDialogOpen(false);
11121
11181
  }, [deleting]);
11122
- const handleDeleteConfirm = useCallback32(async () => {
11182
+ const handleDeleteConfirm = useCallback33(async () => {
11123
11183
  setDeleting(true);
11124
11184
  try {
11125
11185
  await client.delete(documentId);
@@ -11141,24 +11201,25 @@ function ReportActions({
11141
11201
  }
11142
11202
  }, [client, documentId, onDeleted, toast]);
11143
11203
  return /* @__PURE__ */ jsxs35(Fragment13, { children: [
11144
- /* @__PURE__ */ jsx50(
11204
+ /* @__PURE__ */ jsx51(
11145
11205
  SplitActionButton,
11146
11206
  {
11147
11207
  menu: /* @__PURE__ */ jsxs35(Fragment13, { children: [
11148
- /* @__PURE__ */ jsx50(CopyReportIdAction, { reportId }),
11149
- /* @__PURE__ */ jsx50(
11208
+ /* @__PURE__ */ jsx51(CopyReportIdAction, { reportId }),
11209
+ /* @__PURE__ */ jsx51(
11150
11210
  RerunEvaluationAction,
11151
11211
  {
11152
11212
  provenance,
11153
11213
  reportId
11154
11214
  }
11155
11215
  ),
11156
- /* @__PURE__ */ jsx50(MenuDivider3, {}),
11157
- /* @__PURE__ */ jsx50(DownloadReportAction, { documentId, reportId }),
11158
- /* @__PURE__ */ jsx50(CopyReportAction, { documentId }),
11159
- /* @__PURE__ */ jsx50(CopyVisionQueryAction, { reportId }),
11160
- /* @__PURE__ */ jsx50(MenuDivider3, {}),
11161
- /* @__PURE__ */ jsx50(DeleteReportAction, { onRequestDelete: handleRequestDelete })
11216
+ /* @__PURE__ */ jsx51(MenuDivider3, {}),
11217
+ /* @__PURE__ */ jsx51(DownloadReportAction, { documentId, reportId }),
11218
+ /* @__PURE__ */ jsx51(ViewArtifactsAction, { manifest: artifactManifest }),
11219
+ /* @__PURE__ */ jsx51(CopyReportAction, { documentId }),
11220
+ /* @__PURE__ */ jsx51(CopyVisionQueryAction, { reportId }),
11221
+ /* @__PURE__ */ jsx51(MenuDivider3, {}),
11222
+ /* @__PURE__ */ jsx51(DeleteReportAction, { onRequestDelete: handleRequestDelete })
11162
11223
  ] }),
11163
11224
  menuId: "report-actions-menu",
11164
11225
  primary: {
@@ -11168,7 +11229,7 @@ function ReportActions({
11168
11229
  }
11169
11230
  }
11170
11231
  ),
11171
- deleteDialogOpen && /* @__PURE__ */ jsx50(
11232
+ deleteDialogOpen && /* @__PURE__ */ jsx51(
11172
11233
  DeleteConfirmDialog,
11173
11234
  {
11174
11235
  isDeleting: deleting,
@@ -11183,7 +11244,7 @@ function ReportActions({
11183
11244
  // src/components/report-detail/ReportHeader.tsx
11184
11245
  import { ArrowLeftIcon as ArrowLeftIcon2 } from "@sanity/icons";
11185
11246
  import { Button as Button10, Flex as Flex25, Stack as Stack28, Text as Text37 } from "@sanity/ui";
11186
- import { jsx as jsx51, jsxs as jsxs36 } from "react/jsx-runtime";
11247
+ import { jsx as jsx52, jsxs as jsxs36 } from "react/jsx-runtime";
11187
11248
  function ReportHeader({
11188
11249
  completedAt,
11189
11250
  onBack,
@@ -11194,10 +11255,10 @@ function ReportHeader({
11194
11255
  const displayTitle = title ?? tag ?? dateLabel;
11195
11256
  const hasSubtitle = Boolean(title ?? tag);
11196
11257
  return /* @__PURE__ */ jsxs36(Flex25, { align: "center", gap: 3, children: [
11197
- /* @__PURE__ */ jsx51(Button10, { icon: ArrowLeftIcon2, mode: "bleed", onClick: onBack, text: "Back" }),
11258
+ /* @__PURE__ */ jsx52(Button10, { icon: ArrowLeftIcon2, mode: "bleed", onClick: onBack, text: "Back" }),
11198
11259
  /* @__PURE__ */ jsxs36(Stack28, { flex: 1, space: 1, children: [
11199
- /* @__PURE__ */ jsx51(Text37, { size: 4, weight: "bold", children: displayTitle }),
11200
- hasSubtitle && /* @__PURE__ */ jsx51(Text37, { muted: true, size: 2, children: dateLabel })
11260
+ /* @__PURE__ */ jsx52(Text37, { size: 4, weight: "bold", children: displayTitle }),
11261
+ hasSubtitle && /* @__PURE__ */ jsx52(Text37, { muted: true, size: 2, children: dateLabel })
11201
11262
  ] })
11202
11263
  ] });
11203
11264
  }
@@ -11209,13 +11270,13 @@ import { Box as Box27, Flex as Flex28, Stack as Stack30, Text as Text40 } from "
11209
11270
 
11210
11271
  // src/components/report-detail/AreaScoresGrid.tsx
11211
11272
  import React3, {
11212
- useCallback as useCallback33,
11273
+ useCallback as useCallback34,
11213
11274
  useMemo as useMemo13,
11214
11275
  useState as useState25
11215
11276
  } from "react";
11216
11277
  import { WarningOutlineIcon as WarningOutlineIcon2 } from "@sanity/icons";
11217
11278
  import { Box as Box26, Flex as Flex26, Stack as Stack29, Text as Text38 } from "@sanity/ui";
11218
- import { Fragment as Fragment14, jsx as jsx52, jsxs as jsxs37 } from "react/jsx-runtime";
11279
+ import { Fragment as Fragment14, jsx as jsx53, jsxs as jsxs37 } from "react/jsx-runtime";
11219
11280
  var DIMENSION_TOOLTIPS2 = {
11220
11281
  agentOutput: "Quality and completeness of the agent's output. Graded 0\u2013100.",
11221
11282
  assertionPassRate: "Fraction of structural assertions that passed. Graded 0\u2013100.",
@@ -11263,7 +11324,7 @@ function AreaScoresGrid({
11263
11324
  const dimKeys = useMemo13(() => collectDimensionKeys(scores), [scores]);
11264
11325
  const [sortField, setSortField] = useState25("score");
11265
11326
  const [sortDir, setSortDir] = useState25("desc");
11266
- const handleSort = useCallback33(
11327
+ const handleSort = useCallback34(
11267
11328
  (field) => {
11268
11329
  if (field === sortField) {
11269
11330
  setSortDir((d) => d === "asc" ? "desc" : "asc");
@@ -11324,7 +11385,7 @@ function AreaScoresGrid({
11324
11385
  padding: "12px 16px 8px"
11325
11386
  },
11326
11387
  children: [
11327
- /* @__PURE__ */ jsx52(
11388
+ /* @__PURE__ */ jsx53(
11328
11389
  ColHeader2,
11329
11390
  {
11330
11391
  active: sortField === "score",
@@ -11334,7 +11395,7 @@ function AreaScoresGrid({
11334
11395
  tooltip: GLOSSARY.score
11335
11396
  }
11336
11397
  ),
11337
- /* @__PURE__ */ jsx52(
11398
+ /* @__PURE__ */ jsx53(
11338
11399
  ColHeader2,
11339
11400
  {
11340
11401
  active: sortField === "area",
@@ -11343,7 +11404,7 @@ function AreaScoresGrid({
11343
11404
  onClick: () => handleSort("area")
11344
11405
  }
11345
11406
  ),
11346
- dimKeys.map((key) => /* @__PURE__ */ jsx52(
11407
+ dimKeys.map((key) => /* @__PURE__ */ jsx53(
11347
11408
  ColHeader2,
11348
11409
  {
11349
11410
  active: sortField === key,
@@ -11354,7 +11415,7 @@ function AreaScoresGrid({
11354
11415
  },
11355
11416
  key
11356
11417
  )),
11357
- tier !== "narrow" && showLift && /* @__PURE__ */ jsx52(
11418
+ tier !== "narrow" && showLift && /* @__PURE__ */ jsx53(
11358
11419
  ColHeader2,
11359
11420
  {
11360
11421
  active: sortField === "lift",
@@ -11364,23 +11425,23 @@ function AreaScoresGrid({
11364
11425
  tooltip: GLOSSARY.docLift
11365
11426
  }
11366
11427
  ),
11367
- tier === "full" && hasActual && /* @__PURE__ */ jsx52(ColHeader2, { label: "Actual", tooltip: GLOSSARY.actualScore })
11428
+ tier === "full" && hasActual && /* @__PURE__ */ jsx53(ColHeader2, { label: "Actual", tooltip: GLOSSARY.actualScore })
11368
11429
  ]
11369
11430
  }
11370
11431
  ),
11371
11432
  sorted.map((area) => /* @__PURE__ */ jsxs37(React3.Fragment, { children: [
11372
- /* @__PURE__ */ jsx52(
11433
+ /* @__PURE__ */ jsx53(
11373
11434
  AreaRow,
11374
11435
  {
11375
11436
  area,
11376
- delta: perArea?.[area.feature],
11437
+ delta: perArea?.find((p) => p.area === area.feature)?.delta,
11377
11438
  dimKeys,
11378
11439
  hasActual,
11379
11440
  showLift,
11380
11441
  tier
11381
11442
  }
11382
11443
  ),
11383
- modelScoresByFeature && /* @__PURE__ */ jsx52(
11444
+ modelScoresByFeature && /* @__PURE__ */ jsx53(
11384
11445
  ModelSubRows,
11385
11446
  {
11386
11447
  dimKeys,
@@ -11401,7 +11462,7 @@ function ModelSubRows({
11401
11462
  tier
11402
11463
  }) {
11403
11464
  if (!models || models.length === 0) return null;
11404
- return /* @__PURE__ */ jsx52(Fragment14, { children: models.map((entry) => /* @__PURE__ */ jsx52(
11465
+ return /* @__PURE__ */ jsx53(Fragment14, { children: models.map((entry) => /* @__PURE__ */ jsx53(
11405
11466
  ModelRow2,
11406
11467
  {
11407
11468
  dimKeys,
@@ -11441,7 +11502,7 @@ function ModelRow2({
11441
11502
  padding: isNarrow ? "6px 12px 6px 20px" : "6px 16px 6px 28px"
11442
11503
  },
11443
11504
  children: [
11444
- /* @__PURE__ */ jsx52(Flex26, { align: "center", children: /* @__PURE__ */ jsx52(
11505
+ /* @__PURE__ */ jsx53(Flex26, { align: "center", children: /* @__PURE__ */ jsx53(
11445
11506
  Text38,
11446
11507
  {
11447
11508
  size: 1,
@@ -11453,8 +11514,8 @@ function ModelRow2({
11453
11514
  children: Math.round(scores.totalScore)
11454
11515
  }
11455
11516
  ) }),
11456
- /* @__PURE__ */ jsx52(Flex26, { align: "center", gap: 2, children: /* @__PURE__ */ jsx52(Text38, { muted: true, size: 1, children: label }) }),
11457
- dimKeys.map((key) => /* @__PURE__ */ jsx52(
11517
+ /* @__PURE__ */ jsx53(Flex26, { align: "center", gap: 2, children: /* @__PURE__ */ jsx53(Text38, { muted: true, size: 1, children: label }) }),
11518
+ dimKeys.map((key) => /* @__PURE__ */ jsx53(
11458
11519
  DimCell,
11459
11520
  {
11460
11521
  area: label,
@@ -11479,7 +11540,7 @@ function ModelRow2({
11479
11540
  ]
11480
11541
  }
11481
11542
  ),
11482
- tier === "full" && hasActual && /* @__PURE__ */ jsx52(
11543
+ tier === "full" && hasActual && /* @__PURE__ */ jsx53(
11483
11544
  Text38,
11484
11545
  {
11485
11546
  size: 1,
@@ -11522,14 +11583,14 @@ function AreaRow({
11522
11583
  },
11523
11584
  children: [
11524
11585
  /* @__PURE__ */ jsxs37(Flex26, { align: "center", gap: isNarrow ? 0 : 2, children: [
11525
- /* @__PURE__ */ jsx52(
11586
+ /* @__PURE__ */ jsx53(
11526
11587
  HoverTip,
11527
11588
  {
11528
11589
  text: /* @__PURE__ */ jsxs37(Text38, { size: 2, style: { lineHeight: 1.5 }, children: [
11529
- /* @__PURE__ */ jsx52("span", { style: { fontWeight: 600 }, children: area.feature }),
11590
+ /* @__PURE__ */ jsx53("span", { style: { fontWeight: 600 }, children: area.feature }),
11530
11591
  " score:",
11531
11592
  " ",
11532
- /* @__PURE__ */ jsx52(
11593
+ /* @__PURE__ */ jsx53(
11533
11594
  "span",
11534
11595
  {
11535
11596
  style: {
@@ -11540,12 +11601,12 @@ function AreaRow({
11540
11601
  children: Math.round(area.totalScore)
11541
11602
  }
11542
11603
  ),
11543
- /* @__PURE__ */ jsx52("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
11604
+ /* @__PURE__ */ jsx53("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
11544
11605
  ".",
11545
11606
  " ",
11546
11607
  GLOSSARY.score
11547
11608
  ] }),
11548
- children: /* @__PURE__ */ jsx52(
11609
+ children: /* @__PURE__ */ jsx53(
11549
11610
  "div",
11550
11611
  {
11551
11612
  style: {
@@ -11566,11 +11627,11 @@ function AreaRow({
11566
11627
  )
11567
11628
  }
11568
11629
  ),
11569
- !isNarrow && delta != null && delta !== 0 && /* @__PURE__ */ jsx52(HoverTip, { text: GLOSSARY.areaDelta, children: /* @__PURE__ */ jsx52(DeltaIndicator, { delta, icon: true, size: 1 }) })
11630
+ !isNarrow && delta != null && delta !== 0 && /* @__PURE__ */ jsx53(HoverTip, { text: GLOSSARY.areaDelta, children: /* @__PURE__ */ jsx53(DeltaIndicator, { delta, icon: true, size: 1 }) })
11570
11631
  ] }),
11571
11632
  /* @__PURE__ */ jsxs37(Flex26, { align: "center", gap: 2, wrap: "wrap", children: [
11572
- /* @__PURE__ */ jsx52(Text38, { size: 2, weight: "medium", children: area.feature }),
11573
- area.negativeDocLift && showLift && /* @__PURE__ */ jsx52(HoverTip, { text: GLOSSARY.docsHurt, children: /* @__PURE__ */ jsx52(
11633
+ /* @__PURE__ */ jsx53(Text38, { size: 2, weight: "medium", children: area.feature }),
11634
+ area.negativeDocLift && showLift && /* @__PURE__ */ jsx53(HoverTip, { text: GLOSSARY.docsHurt, children: /* @__PURE__ */ jsx53(
11574
11635
  "span",
11575
11636
  {
11576
11637
  style: {
@@ -11583,11 +11644,11 @@ function AreaRow({
11583
11644
  gap: 3,
11584
11645
  padding: "1px 5px"
11585
11646
  },
11586
- children: /* @__PURE__ */ jsx52(WarningOutlineIcon2, {})
11647
+ children: /* @__PURE__ */ jsx53(WarningOutlineIcon2, {})
11587
11648
  }
11588
11649
  ) })
11589
11650
  ] }),
11590
- dimKeys.map((key) => /* @__PURE__ */ jsx52(
11651
+ dimKeys.map((key) => /* @__PURE__ */ jsx53(
11591
11652
  DimCell,
11592
11653
  {
11593
11654
  area: area.feature,
@@ -11596,11 +11657,11 @@ function AreaRow({
11596
11657
  },
11597
11658
  key
11598
11659
  )),
11599
- !isNarrow && showLift && /* @__PURE__ */ jsx52(
11660
+ !isNarrow && showLift && /* @__PURE__ */ jsx53(
11600
11661
  HoverTip,
11601
11662
  {
11602
11663
  text: /* @__PURE__ */ jsxs37(Text38, { size: 2, style: { lineHeight: 1.5 }, children: [
11603
- /* @__PURE__ */ jsx52("span", { style: { fontWeight: 600 }, children: area.feature }),
11664
+ /* @__PURE__ */ jsx53("span", { style: { fontWeight: 600 }, children: area.feature }),
11604
11665
  " doc lift:",
11605
11666
  " ",
11606
11667
  /* @__PURE__ */ jsxs37(
@@ -11638,11 +11699,11 @@ function AreaRow({
11638
11699
  )
11639
11700
  }
11640
11701
  ),
11641
- tier === "full" && hasActual && /* @__PURE__ */ jsx52(
11702
+ tier === "full" && hasActual && /* @__PURE__ */ jsx53(
11642
11703
  HoverTip,
11643
11704
  {
11644
11705
  text: area.actualScore != null ? `${area.feature} actual score: ${Math.round(area.actualScore)}/100. ${GLOSSARY.actualScore}` : `No agentic data for ${area.feature}.`,
11645
- children: /* @__PURE__ */ jsx52(
11706
+ children: /* @__PURE__ */ jsx53(
11646
11707
  Text38,
11647
11708
  {
11648
11709
  size: 2,
@@ -11672,17 +11733,17 @@ function DimCell({
11672
11733
  const tooltip = dimKey ? DIMENSION_TOOLTIPS2[dimKey] : "";
11673
11734
  const textSize = size === "small" ? 0 : 1;
11674
11735
  const barHeight = size === "small" ? 3 : 4;
11675
- return /* @__PURE__ */ jsx52(
11736
+ return /* @__PURE__ */ jsx53(
11676
11737
  HoverTip,
11677
11738
  {
11678
11739
  text: /* @__PURE__ */ jsxs37(Text38, { size: 2, style: { lineHeight: 1.5 }, children: [
11679
- /* @__PURE__ */ jsx52("span", { style: { fontWeight: 600 }, children: area }),
11740
+ /* @__PURE__ */ jsx53("span", { style: { fontWeight: 600 }, children: area }),
11680
11741
  " \u2192",
11681
11742
  " ",
11682
- /* @__PURE__ */ jsx52("span", { style: { fontWeight: 600 }, children: dim }),
11743
+ /* @__PURE__ */ jsx53("span", { style: { fontWeight: 600 }, children: dim }),
11683
11744
  ":",
11684
11745
  " ",
11685
- /* @__PURE__ */ jsx52(
11746
+ /* @__PURE__ */ jsx53(
11686
11747
  "span",
11687
11748
  {
11688
11749
  style: {
@@ -11693,13 +11754,13 @@ function DimCell({
11693
11754
  children: Math.round(value)
11694
11755
  }
11695
11756
  ),
11696
- /* @__PURE__ */ jsx52("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
11757
+ /* @__PURE__ */ jsx53("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
11697
11758
  ".",
11698
11759
  " ",
11699
11760
  tooltip
11700
11761
  ] }),
11701
11762
  children: /* @__PURE__ */ jsxs37(Stack29, { space: 1, style: { width: "100%" }, children: [
11702
- /* @__PURE__ */ jsx52(
11763
+ /* @__PURE__ */ jsx53(
11703
11764
  Text38,
11704
11765
  {
11705
11766
  size: textSize,
@@ -11711,7 +11772,7 @@ function DimCell({
11711
11772
  children: Math.round(value)
11712
11773
  }
11713
11774
  ),
11714
- /* @__PURE__ */ jsx52(
11775
+ /* @__PURE__ */ jsx53(
11715
11776
  "div",
11716
11777
  {
11717
11778
  style: {
@@ -11721,7 +11782,7 @@ function DimCell({
11721
11782
  overflow: "hidden",
11722
11783
  width: "100%"
11723
11784
  },
11724
- children: /* @__PURE__ */ jsx52(
11785
+ children: /* @__PURE__ */ jsx53(
11725
11786
  "div",
11726
11787
  {
11727
11788
  style: {
@@ -11746,7 +11807,7 @@ function ColHeader2({
11746
11807
  onClick,
11747
11808
  tooltip
11748
11809
  }) {
11749
- const handleKeyDown = useCallback33(
11810
+ const handleKeyDown = useCallback34(
11750
11811
  (e) => {
11751
11812
  if (onClick && (e.key === "Enter" || e.key === " ")) {
11752
11813
  e.preventDefault();
@@ -11757,7 +11818,7 @@ function ColHeader2({
11757
11818
  );
11758
11819
  const arrow = active ? direction === "asc" ? " \u2191" : " \u2193" : "";
11759
11820
  return /* @__PURE__ */ jsxs37(Flex26, { align: "center", gap: 1, children: [
11760
- /* @__PURE__ */ jsx52(
11821
+ /* @__PURE__ */ jsx53(
11761
11822
  "div",
11762
11823
  {
11763
11824
  onClick,
@@ -11786,14 +11847,14 @@ function ColHeader2({
11786
11847
  )
11787
11848
  }
11788
11849
  ),
11789
- tooltip && /* @__PURE__ */ jsx52(InfoTip, { text: tooltip })
11850
+ tooltip && /* @__PURE__ */ jsx53(InfoTip, { text: tooltip })
11790
11851
  ] });
11791
11852
  }
11792
11853
 
11793
11854
  // src/components/report-detail/ModelSelector.tsx
11794
- import { useCallback as useCallback34 } from "react";
11855
+ import { useCallback as useCallback35 } from "react";
11795
11856
  import { Flex as Flex27, Text as Text39 } from "@sanity/ui";
11796
- import { jsx as jsx53, jsxs as jsxs38 } from "react/jsx-runtime";
11857
+ import { jsx as jsx54, jsxs as jsxs38 } from "react/jsx-runtime";
11797
11858
  var pillBase = {
11798
11859
  borderColor: "var(--card-border-color)",
11799
11860
  borderRadius: 999,
@@ -11825,7 +11886,7 @@ function ModelSelector({
11825
11886
  onChange
11826
11887
  }) {
11827
11888
  return /* @__PURE__ */ jsxs38(Flex27, { align: "center", gap: 1, wrap: "wrap", children: [
11828
- /* @__PURE__ */ jsx53(
11889
+ /* @__PURE__ */ jsx54(
11829
11890
  Pill2,
11830
11891
  {
11831
11892
  isSelected: selection === null,
@@ -11833,7 +11894,7 @@ function ModelSelector({
11833
11894
  onClick: () => onChange(null)
11834
11895
  }
11835
11896
  ),
11836
- models.map((model) => /* @__PURE__ */ jsx53(
11897
+ models.map((model) => /* @__PURE__ */ jsx54(
11837
11898
  Pill2,
11838
11899
  {
11839
11900
  isSelected: selection === model.modelId,
@@ -11842,7 +11903,7 @@ function ModelSelector({
11842
11903
  },
11843
11904
  model.modelId
11844
11905
  )),
11845
- /* @__PURE__ */ jsx53(
11906
+ /* @__PURE__ */ jsx54(
11846
11907
  "div",
11847
11908
  {
11848
11909
  style: {
@@ -11853,7 +11914,7 @@ function ModelSelector({
11853
11914
  }
11854
11915
  }
11855
11916
  ),
11856
- /* @__PURE__ */ jsx53(
11917
+ /* @__PURE__ */ jsx54(
11857
11918
  Pill2,
11858
11919
  {
11859
11920
  isSelected: selection === "expanded",
@@ -11868,7 +11929,7 @@ function Pill2({
11868
11929
  label,
11869
11930
  onClick
11870
11931
  }) {
11871
- const handleKeyDown = useCallback34(
11932
+ const handleKeyDown = useCallback35(
11872
11933
  (e) => {
11873
11934
  if (e.key === "Enter" || e.key === " ") {
11874
11935
  e.preventDefault();
@@ -11877,7 +11938,7 @@ function Pill2({
11877
11938
  },
11878
11939
  [onClick]
11879
11940
  );
11880
- return /* @__PURE__ */ jsx53(
11941
+ return /* @__PURE__ */ jsx54(
11881
11942
  "span",
11882
11943
  {
11883
11944
  onClick,
@@ -11885,7 +11946,7 @@ function Pill2({
11885
11946
  role: "button",
11886
11947
  style: isSelected ? pillSelected : pillDefault,
11887
11948
  tabIndex: 0,
11888
- children: /* @__PURE__ */ jsx53(
11949
+ children: /* @__PURE__ */ jsx54(
11889
11950
  Text39,
11890
11951
  {
11891
11952
  size: 1,
@@ -11901,13 +11962,13 @@ function Pill2({
11901
11962
  }
11902
11963
 
11903
11964
  // src/components/report-detail/useModelSelection.ts
11904
- import { useCallback as useCallback35, useMemo as useMemo14, useState as useState26 } from "react";
11965
+ import { useCallback as useCallback36, useMemo as useMemo14, useState as useState26 } from "react";
11905
11966
  function useModelSelection({
11906
11967
  scores,
11907
11968
  perModel
11908
11969
  }) {
11909
11970
  const [selection, setSelection] = useState26(null);
11910
- const onSelectionChange = useCallback35((next) => {
11971
+ const onSelectionChange = useCallback36((next) => {
11911
11972
  setSelection(next);
11912
11973
  }, []);
11913
11974
  const isExpanded = selection === "expanded";
@@ -11929,7 +11990,7 @@ function useModelSelection({
11929
11990
  }
11930
11991
 
11931
11992
  // src/components/report-detail/StrengthsList.tsx
11932
- import { jsx as jsx54, jsxs as jsxs39 } from "react/jsx-runtime";
11993
+ import { jsx as jsx55, jsxs as jsxs39 } from "react/jsx-runtime";
11933
11994
  function StrengthsList({
11934
11995
  mode,
11935
11996
  scores,
@@ -11956,10 +12017,10 @@ function StrengthsList({
11956
12017
  return /* @__PURE__ */ jsxs39(Stack30, { space: 5, children: [
11957
12018
  /* @__PURE__ */ jsxs39(Stack30, { space: 3, children: [
11958
12019
  /* @__PURE__ */ jsxs39(Flex28, { align: "center", gap: 2, wrap: "wrap", children: [
11959
- /* @__PURE__ */ jsx54(CheckmarkCircleIcon2, { style: { color: "#34d399" } }),
11960
- /* @__PURE__ */ jsx54(Text40, { size: 2, weight: "medium", children: "Strong Areas (70+)" }),
11961
- /* @__PURE__ */ jsx54(InfoTip, { text: GLOSSARY.strengths }),
11962
- hasModels && /* @__PURE__ */ jsx54(Box27, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx54(
12020
+ /* @__PURE__ */ jsx55(CheckmarkCircleIcon2, { style: { color: "#34d399" } }),
12021
+ /* @__PURE__ */ jsx55(Text40, { size: 2, weight: "medium", children: "Strong Areas (70+)" }),
12022
+ /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.strengths }),
12023
+ hasModels && /* @__PURE__ */ jsx55(Box27, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx55(
11963
12024
  ModelSelector,
11964
12025
  {
11965
12026
  models: perModel,
@@ -11968,7 +12029,7 @@ function StrengthsList({
11968
12029
  }
11969
12030
  ) })
11970
12031
  ] }),
11971
- /* @__PURE__ */ jsx54(
12032
+ /* @__PURE__ */ jsx55(
11972
12033
  AreaScoresGrid,
11973
12034
  {
11974
12035
  mode,
@@ -11979,23 +12040,23 @@ function StrengthsList({
11979
12040
  )
11980
12041
  ] }),
11981
12042
  retrievalSuccesses.length > 0 && /* @__PURE__ */ jsxs39(Box27, { style: neutralCardStyle, children: [
11982
- /* @__PURE__ */ jsx54(
12043
+ /* @__PURE__ */ jsx55(
11983
12044
  Box27,
11984
12045
  {
11985
12046
  padding: 4,
11986
12047
  style: { borderBottom: "1px solid var(--card-border-color)" },
11987
12048
  children: /* @__PURE__ */ jsxs39(Flex28, { align: "center", gap: 2, children: [
11988
- /* @__PURE__ */ jsx54(SearchIcon8, { style: { color: "#34d399" } }),
12049
+ /* @__PURE__ */ jsx55(SearchIcon8, { style: { color: "#34d399" } }),
11989
12050
  /* @__PURE__ */ jsxs39(Text40, { size: 2, weight: "medium", children: [
11990
12051
  "Retrieval Successes (",
11991
12052
  Math.round(EFFICIENCY_POSITIVE * 100),
11992
12053
  "%+ efficiency)"
11993
12054
  ] }),
11994
- /* @__PURE__ */ jsx54(InfoTip, { text: GLOSSARY.retrievalExcellence })
12055
+ /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.retrievalExcellence })
11995
12056
  ] })
11996
12057
  }
11997
12058
  ),
11998
- /* @__PURE__ */ jsx54(Stack30, { children: retrievalSuccesses.map((area, i) => /* @__PURE__ */ jsxs39(
12059
+ /* @__PURE__ */ jsx55(Stack30, { children: retrievalSuccesses.map((area, i) => /* @__PURE__ */ jsxs39(
11999
12060
  Flex28,
12000
12061
  {
12001
12062
  align: "center",
@@ -12003,8 +12064,8 @@ function StrengthsList({
12003
12064
  padding: 4,
12004
12065
  style: i > 0 ? dividerStyle : void 0,
12005
12066
  children: [
12006
- /* @__PURE__ */ jsx54(Text40, { size: 2, children: area.feature }),
12007
- /* @__PURE__ */ jsx54(
12067
+ /* @__PURE__ */ jsx55(Text40, { size: 2, children: area.feature }),
12068
+ /* @__PURE__ */ jsx55(
12008
12069
  "span",
12009
12070
  {
12010
12071
  style: {
@@ -12035,7 +12096,7 @@ import {
12035
12096
  ArrowDownIcon as ArrowDownIcon2
12036
12097
  } from "@sanity/icons";
12037
12098
  import { Box as Box28, Flex as Flex29, Stack as Stack31, Text as Text41 } from "@sanity/ui";
12038
- import { jsx as jsx55, jsxs as jsxs40 } from "react/jsx-runtime";
12099
+ import { jsx as jsx56, jsxs as jsxs40 } from "react/jsx-runtime";
12039
12100
  function WeaknessesList({
12040
12101
  mode,
12041
12102
  scores,
@@ -12068,10 +12129,10 @@ function WeaknessesList({
12068
12129
  return /* @__PURE__ */ jsxs40(Stack31, { space: 5, children: [
12069
12130
  weakAreas.length > 0 && /* @__PURE__ */ jsxs40(Stack31, { space: 3, children: [
12070
12131
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, wrap: "wrap", children: [
12071
- /* @__PURE__ */ jsx55(ErrorOutlineIcon3, { style: { color: "#f87171" } }),
12072
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Weak Areas (<70)" }),
12073
- /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.weakAreas }),
12074
- hasModels && /* @__PURE__ */ jsx55(Box28, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx55(
12132
+ /* @__PURE__ */ jsx56(ErrorOutlineIcon3, { style: { color: "#f87171" } }),
12133
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Weak Areas (<70)" }),
12134
+ /* @__PURE__ */ jsx56(InfoTip, { text: GLOSSARY.weakAreas }),
12135
+ hasModels && /* @__PURE__ */ jsx56(Box28, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx56(
12075
12136
  ModelSelector,
12076
12137
  {
12077
12138
  models: perModel,
@@ -12080,7 +12141,7 @@ function WeaknessesList({
12080
12141
  }
12081
12142
  ) })
12082
12143
  ] }),
12083
- /* @__PURE__ */ jsx55(
12144
+ /* @__PURE__ */ jsx56(
12084
12145
  AreaScoresGrid,
12085
12146
  {
12086
12147
  mode,
@@ -12092,11 +12153,11 @@ function WeaknessesList({
12092
12153
  ] }),
12093
12154
  docsHurt.length > 0 && /* @__PURE__ */ jsxs40(Stack31, { space: 3, children: [
12094
12155
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12095
- /* @__PURE__ */ jsx55(ErrorOutlineIcon3, { style: { color: "#f87171" } }),
12096
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Docs Hurt Performance (Negative Doc Lift)" }),
12097
- /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.docsHurt })
12156
+ /* @__PURE__ */ jsx56(ErrorOutlineIcon3, { style: { color: "#f87171" } }),
12157
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Docs Hurt Performance (Negative Doc Lift)" }),
12158
+ /* @__PURE__ */ jsx56(InfoTip, { text: GLOSSARY.docsHurt })
12098
12159
  ] }),
12099
- /* @__PURE__ */ jsx55(Box28, { style: sectionStyle("red"), children: docsHurt.map((area, i) => /* @__PURE__ */ jsxs40(
12160
+ /* @__PURE__ */ jsx56(Box28, { style: sectionStyle("red"), children: docsHurt.map((area, i) => /* @__PURE__ */ jsxs40(
12100
12161
  Box28,
12101
12162
  {
12102
12163
  padding: 4,
@@ -12104,8 +12165,8 @@ function WeaknessesList({
12104
12165
  children: [
12105
12166
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", justify: "space-between", wrap: "wrap", children: [
12106
12167
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12107
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: area.feature }),
12108
- /* @__PURE__ */ jsx55(
12168
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: area.feature }),
12169
+ /* @__PURE__ */ jsx56(
12109
12170
  "span",
12110
12171
  {
12111
12172
  style: {
@@ -12120,7 +12181,7 @@ function WeaknessesList({
12120
12181
  }
12121
12182
  )
12122
12183
  ] }),
12123
- /* @__PURE__ */ jsx55(
12184
+ /* @__PURE__ */ jsx56(
12124
12185
  "span",
12125
12186
  {
12126
12187
  style: {
@@ -12133,7 +12194,7 @@ function WeaknessesList({
12133
12194
  }
12134
12195
  )
12135
12196
  ] }),
12136
- /* @__PURE__ */ jsx55(Box28, { paddingTop: 2, children: /* @__PURE__ */ jsxs40(Text41, { muted: true, size: 2, children: [
12197
+ /* @__PURE__ */ jsx56(Box28, { paddingTop: 2, children: /* @__PURE__ */ jsxs40(Text41, { muted: true, size: 2, children: [
12137
12198
  area.invertedRetrievalGap && /* @__PURE__ */ jsxs40("span", { style: { color: "#fbbf24" }, children: [
12138
12199
  "Agent does better by NOT finding these docs.",
12139
12200
  " "
@@ -12151,11 +12212,11 @@ function WeaknessesList({
12151
12212
  ] }),
12152
12213
  retrievalIssues.length > 0 && /* @__PURE__ */ jsxs40(Stack31, { space: 3, children: [
12153
12214
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12154
- /* @__PURE__ */ jsx55(SearchIcon9, { style: { color: "#fbbf24" } }),
12155
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Retrieval Issues (<70% efficiency)" }),
12156
- /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.retrievalIssues })
12215
+ /* @__PURE__ */ jsx56(SearchIcon9, { style: { color: "#fbbf24" } }),
12216
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Retrieval Issues (<70% efficiency)" }),
12217
+ /* @__PURE__ */ jsx56(InfoTip, { text: GLOSSARY.retrievalIssues })
12157
12218
  ] }),
12158
- /* @__PURE__ */ jsx55(Box28, { style: sectionStyle("amber"), children: retrievalIssues.map((area, i) => /* @__PURE__ */ jsxs40(
12219
+ /* @__PURE__ */ jsx56(Box28, { style: sectionStyle("amber"), children: retrievalIssues.map((area, i) => /* @__PURE__ */ jsxs40(
12159
12220
  Box28,
12160
12221
  {
12161
12222
  padding: 4,
@@ -12163,8 +12224,8 @@ function WeaknessesList({
12163
12224
  children: [
12164
12225
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", justify: "space-between", wrap: "wrap", children: [
12165
12226
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12166
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: area.feature }),
12167
- /* @__PURE__ */ jsx55(
12227
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: area.feature }),
12228
+ /* @__PURE__ */ jsx56(
12168
12229
  "span",
12169
12230
  {
12170
12231
  style: {
@@ -12179,7 +12240,7 @@ function WeaknessesList({
12179
12240
  }
12180
12241
  )
12181
12242
  ] }),
12182
- /* @__PURE__ */ jsx55(
12243
+ /* @__PURE__ */ jsx56(
12183
12244
  "span",
12184
12245
  {
12185
12246
  style: {
@@ -12192,7 +12253,7 @@ function WeaknessesList({
12192
12253
  }
12193
12254
  )
12194
12255
  ] }),
12195
- /* @__PURE__ */ jsx55(Box28, { paddingTop: 2, children: /* @__PURE__ */ jsxs40(Text41, { muted: true, size: 2, children: [
12256
+ /* @__PURE__ */ jsx56(Box28, { paddingTop: 2, children: /* @__PURE__ */ jsxs40(Text41, { muted: true, size: 2, children: [
12196
12257
  "Actual score (",
12197
12258
  Math.round(area.actualScore ?? 0),
12198
12259
  ") is much lower than ceiling (",
@@ -12209,19 +12270,19 @@ function WeaknessesList({
12209
12270
  ] }),
12210
12271
  dimWeaknesses.length > 0 && /* @__PURE__ */ jsxs40(Stack31, { space: 3, children: [
12211
12272
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12212
- /* @__PURE__ */ jsx55(WarningOutlineIcon3, { style: { color: "#fbbf24" } }),
12213
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Dimension Weaknesses (<50)" }),
12214
- /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.dimWeaknesses })
12273
+ /* @__PURE__ */ jsx56(WarningOutlineIcon3, { style: { color: "#fbbf24" } }),
12274
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Dimension Weaknesses (<50)" }),
12275
+ /* @__PURE__ */ jsx56(InfoTip, { text: GLOSSARY.dimWeaknesses })
12215
12276
  ] }),
12216
- /* @__PURE__ */ jsx55(Box28, { style: neutralCardStyle, children: dimWeaknesses.map(({ area, dims }, i) => /* @__PURE__ */ jsxs40(
12277
+ /* @__PURE__ */ jsx56(Box28, { style: neutralCardStyle, children: dimWeaknesses.map(({ area, dims }, i) => /* @__PURE__ */ jsxs40(
12217
12278
  Box28,
12218
12279
  {
12219
12280
  padding: 4,
12220
12281
  style: i > 0 ? dividerStyle : void 0,
12221
12282
  children: [
12222
12283
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, paddingBottom: 2, children: [
12223
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: area.feature }),
12224
- /* @__PURE__ */ jsx55(
12284
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: area.feature }),
12285
+ /* @__PURE__ */ jsx56(
12225
12286
  "span",
12226
12287
  {
12227
12288
  style: {
@@ -12236,7 +12297,7 @@ function WeaknessesList({
12236
12297
  }
12237
12298
  )
12238
12299
  ] }),
12239
- /* @__PURE__ */ jsx55(Flex29, { gap: 2, wrap: "wrap", children: dims.map((w) => /* @__PURE__ */ jsx55(HoverTip, { text: w.tip, children: /* @__PURE__ */ jsxs40(
12300
+ /* @__PURE__ */ jsx56(Flex29, { gap: 2, wrap: "wrap", children: dims.map((w) => /* @__PURE__ */ jsx56(HoverTip, { text: w.tip, children: /* @__PURE__ */ jsxs40(
12240
12301
  "span",
12241
12302
  {
12242
12303
  style: {
@@ -12259,20 +12320,22 @@ function WeaknessesList({
12259
12320
  )) })
12260
12321
  ] }),
12261
12322
  FEATURE_FLAGS.showRegressedSinceLastRun.enabled && regressed.length > 0 && /* @__PURE__ */ jsxs40(Box28, { style: neutralCardStyle, children: [
12262
- /* @__PURE__ */ jsx55(
12323
+ /* @__PURE__ */ jsx56(
12263
12324
  Box28,
12264
12325
  {
12265
12326
  padding: 4,
12266
12327
  style: { borderBottom: "1px solid var(--card-border-color)" },
12267
12328
  children: /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12268
- /* @__PURE__ */ jsx55(ArrowDownIcon2, { style: { color: "#f87171" } }),
12269
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Regressed Since Last Run" })
12329
+ /* @__PURE__ */ jsx56(ArrowDownIcon2, { style: { color: "#f87171" } }),
12330
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Regressed Since Last Run" })
12270
12331
  ] })
12271
12332
  }
12272
12333
  ),
12273
- /* @__PURE__ */ jsx55(Stack31, { children: regressed.map((featureName, i) => {
12334
+ /* @__PURE__ */ jsx56(Stack31, { children: regressed.map((featureName, i) => {
12274
12335
  const area = scores.find((s) => s.feature === featureName);
12275
- const areaDelta = perArea?.[featureName];
12336
+ const areaDelta = perArea?.find(
12337
+ (p) => p.area === featureName
12338
+ )?.delta;
12276
12339
  return /* @__PURE__ */ jsxs40(
12277
12340
  Flex29,
12278
12341
  {
@@ -12281,10 +12344,10 @@ function WeaknessesList({
12281
12344
  padding: 4,
12282
12345
  style: i > 0 ? dividerStyle : void 0,
12283
12346
  children: [
12284
- /* @__PURE__ */ jsx55(Text41, { size: 2, children: featureName }),
12347
+ /* @__PURE__ */ jsx56(Text41, { size: 2, children: featureName }),
12285
12348
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 3, children: [
12286
- areaDelta != null && /* @__PURE__ */ jsx55(DeltaIndicator, { delta: areaDelta, icon: true }),
12287
- area && /* @__PURE__ */ jsx55(
12349
+ areaDelta != null && /* @__PURE__ */ jsx56(DeltaIndicator, { delta: areaDelta, icon: true }),
12350
+ area && /* @__PURE__ */ jsx56(
12288
12351
  "span",
12289
12352
  {
12290
12353
  style: {
@@ -12307,22 +12370,22 @@ function WeaknessesList({
12307
12370
  }) })
12308
12371
  ] }),
12309
12372
  efficiencyAnomalies.length > 0 && /* @__PURE__ */ jsxs40(Box28, { style: neutralCardStyle, children: [
12310
- /* @__PURE__ */ jsx55(
12373
+ /* @__PURE__ */ jsx56(
12311
12374
  Box28,
12312
12375
  {
12313
12376
  padding: 4,
12314
12377
  style: { borderBottom: "1px solid var(--card-border-color)" },
12315
12378
  children: /* @__PURE__ */ jsxs40(Stack31, { space: 2, children: [
12316
12379
  /* @__PURE__ */ jsxs40(Flex29, { align: "center", gap: 2, children: [
12317
- /* @__PURE__ */ jsx55(BoltIcon, { style: { color: "#fbbf24" } }),
12318
- /* @__PURE__ */ jsx55(Text41, { size: 2, weight: "medium", children: "Efficiency Anomalies (>100%)" }),
12319
- /* @__PURE__ */ jsx55(InfoTip, { text: GLOSSARY.efficiencyAnomalies })
12380
+ /* @__PURE__ */ jsx56(BoltIcon, { style: { color: "#fbbf24" } }),
12381
+ /* @__PURE__ */ jsx56(Text41, { size: 2, weight: "medium", children: "Efficiency Anomalies (>100%)" }),
12382
+ /* @__PURE__ */ jsx56(InfoTip, { text: GLOSSARY.efficiencyAnomalies })
12320
12383
  ] }),
12321
- /* @__PURE__ */ jsx55(Text41, { muted: true, size: 2, children: "Agent outperforms injected docs \u2014 may indicate doc quality issues or agent memorization." })
12384
+ /* @__PURE__ */ jsx56(Text41, { muted: true, size: 2, children: "Agent outperforms injected docs \u2014 may indicate doc quality issues or agent memorization." })
12322
12385
  ] })
12323
12386
  }
12324
12387
  ),
12325
- /* @__PURE__ */ jsx55(Stack31, { children: efficiencyAnomalies.map((area, i) => /* @__PURE__ */ jsxs40(
12388
+ /* @__PURE__ */ jsx56(Stack31, { children: efficiencyAnomalies.map((area, i) => /* @__PURE__ */ jsxs40(
12326
12389
  Flex29,
12327
12390
  {
12328
12391
  align: "center",
@@ -12330,8 +12393,8 @@ function WeaknessesList({
12330
12393
  padding: 4,
12331
12394
  style: i > 0 ? dividerStyle : void 0,
12332
12395
  children: [
12333
- /* @__PURE__ */ jsx55(Text41, { size: 2, children: area.feature }),
12334
- /* @__PURE__ */ jsx55(
12396
+ /* @__PURE__ */ jsx56(Text41, { size: 2, children: area.feature }),
12397
+ /* @__PURE__ */ jsx56(
12335
12398
  "span",
12336
12399
  {
12337
12400
  style: {
@@ -12360,11 +12423,11 @@ var tipArea = {
12360
12423
  };
12361
12424
  function dimTip(area, dim, score, description) {
12362
12425
  return /* @__PURE__ */ jsxs40(Text41, { size: 2, style: { lineHeight: 1.5 }, children: [
12363
- /* @__PURE__ */ jsx55("span", { style: tipArea, children: area }),
12426
+ /* @__PURE__ */ jsx56("span", { style: tipArea, children: area }),
12364
12427
  " scores",
12365
12428
  " ",
12366
- /* @__PURE__ */ jsx55("span", { style: tipValue, children: score }),
12367
- /* @__PURE__ */ jsx55("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
12429
+ /* @__PURE__ */ jsx56("span", { style: tipValue, children: score }),
12430
+ /* @__PURE__ */ jsx56("span", { style: { color: "var(--card-muted-fg-color)" }, children: "/100" }),
12368
12431
  " on",
12369
12432
  " ",
12370
12433
  dim.toLowerCase(),
@@ -12393,7 +12456,7 @@ function getDimensionWeaknesses(area) {
12393
12456
  }
12394
12457
 
12395
12458
  // src/components/report-detail/ReportDetail.tsx
12396
- import { jsx as jsx56, jsxs as jsxs41 } from "react/jsx-runtime";
12459
+ import { jsx as jsx57, jsxs as jsxs41 } from "react/jsx-runtime";
12397
12460
  var OVERVIEW_TAB = { id: "overview", label: "Overview" };
12398
12461
  var DIAGNOSTICS_TAB = { id: "diagnostics", label: "Diagnostics" };
12399
12462
  var ACTIVITY_TAB = { id: "activity", label: "Agent Activity" };
@@ -12456,18 +12519,18 @@ function ReportDetail({
12456
12519
  if (disabledTabs.has(parsed)) return "overview";
12457
12520
  return tabs.some((t) => t.id === parsed) ? parsed : "overview";
12458
12521
  }, [activeTab, disabledTabs, tabs]);
12459
- const handleTabClick = useCallback36(
12522
+ const handleTabClick = useCallback37(
12460
12523
  (tabId) => {
12461
12524
  onTabChange(tabId === "overview" ? null : tabId, null, null);
12462
12525
  },
12463
12526
  [onTabChange]
12464
12527
  );
12465
12528
  if (loading) {
12466
- return /* @__PURE__ */ jsx56(LoadingState, { message: "Loading report\u2026" });
12529
+ return /* @__PURE__ */ jsx57(LoadingState, { message: "Loading report\u2026" });
12467
12530
  }
12468
12531
  if (!report || !summary) {
12469
- return /* @__PURE__ */ jsx56(Box29, { padding: 5, children: /* @__PURE__ */ jsxs41(Stack32, { space: 4, children: [
12470
- /* @__PURE__ */ jsx56(
12532
+ return /* @__PURE__ */ jsx57(Box29, { padding: 5, children: /* @__PURE__ */ jsxs41(Stack32, { space: 4, children: [
12533
+ /* @__PURE__ */ jsx57(
12471
12534
  Button11,
12472
12535
  {
12473
12536
  icon: ArrowLeftIcon3,
@@ -12476,18 +12539,18 @@ function ReportDetail({
12476
12539
  text: "Back"
12477
12540
  }
12478
12541
  ),
12479
- /* @__PURE__ */ jsx56(Text42, { align: "center", muted: true, size: 3, children: "Report not found" })
12542
+ /* @__PURE__ */ jsx57(Text42, { align: "center", muted: true, size: 3, children: "Report not found" })
12480
12543
  ] }) });
12481
12544
  }
12482
12545
  const { comparison, provenance } = report;
12483
12546
  const totalTests = summary.scores.reduce((n, s) => n + s.testCount, 0);
12484
- return /* @__PURE__ */ jsx56(
12547
+ return /* @__PURE__ */ jsx57(
12485
12548
  ReportArtifactProvider,
12486
12549
  {
12487
12550
  runId: report.provenance?.runId,
12488
12551
  manifest: summary?.artifactManifest,
12489
- children: /* @__PURE__ */ jsx56(Box29, { padding: 4, children: /* @__PURE__ */ jsxs41(Stack32, { space: 5, children: [
12490
- /* @__PURE__ */ jsx56(
12552
+ children: /* @__PURE__ */ jsx57(Box29, { padding: 4, children: /* @__PURE__ */ jsxs41(Stack32, { space: 5, children: [
12553
+ /* @__PURE__ */ jsx57(
12491
12554
  ReportHeader,
12492
12555
  {
12493
12556
  completedAt: report.completedAt,
@@ -12497,10 +12560,10 @@ function ReportDetail({
12497
12560
  }
12498
12561
  ),
12499
12562
  /* @__PURE__ */ jsxs41(Flex30, { align: "center", gap: 2, wrap: "wrap", children: [
12500
- /* @__PURE__ */ jsx56(TabList, { space: 1, children: tabs.map((tab) => {
12563
+ /* @__PURE__ */ jsx57(TabList, { space: 1, children: tabs.map((tab) => {
12501
12564
  const isDisabled = disabledTabs.has(tab.id);
12502
12565
  const tooltip = getDisabledTabTooltip(tab.id, summary);
12503
- const tabElement = /* @__PURE__ */ jsx56(
12566
+ const tabElement = /* @__PURE__ */ jsx57(
12504
12567
  Tab,
12505
12568
  {
12506
12569
  "aria-controls": `panel-${tab.id}`,
@@ -12511,29 +12574,30 @@ function ReportDetail({
12511
12574
  selected: currentTab === tab.id
12512
12575
  }
12513
12576
  );
12514
- return isDisabled && tooltip ? /* @__PURE__ */ jsx56(
12577
+ return isDisabled && tooltip ? /* @__PURE__ */ jsx57(
12515
12578
  Tooltip10,
12516
12579
  {
12517
- content: /* @__PURE__ */ jsx56(Box29, { padding: 2, style: { maxWidth: 280 }, children: tooltip }),
12580
+ content: /* @__PURE__ */ jsx57(Box29, { padding: 2, style: { maxWidth: 280 }, children: tooltip }),
12518
12581
  placement: "bottom",
12519
12582
  portal: true,
12520
- children: /* @__PURE__ */ jsx56("span", { style: { display: "inline-block" }, children: tabElement })
12583
+ children: /* @__PURE__ */ jsx57("span", { style: { display: "inline-block" }, children: tabElement })
12521
12584
  },
12522
12585
  tab.id
12523
- ) : /* @__PURE__ */ jsx56("span", { children: tabElement }, tab.id);
12586
+ ) : /* @__PURE__ */ jsx57("span", { children: tabElement }, tab.id);
12524
12587
  }) }),
12525
12588
  /* @__PURE__ */ jsxs41(Flex30, { align: "center", gap: 2, style: { marginLeft: "auto" }, children: [
12526
- /* @__PURE__ */ jsx56(
12589
+ /* @__PURE__ */ jsx57(
12527
12590
  HoverTip,
12528
12591
  {
12529
12592
  text: SOURCE_TIP[provenance.source.name] ?? GLOSSARY.reportMode,
12530
- children: /* @__PURE__ */ jsx56(Badge10, { mode: "outline", tone: "default", children: provenance.source.name })
12593
+ children: /* @__PURE__ */ jsx57(Badge10, { mode: "outline", tone: "default", children: provenance.source.name })
12531
12594
  }
12532
12595
  ),
12533
- /* @__PURE__ */ jsx56(HoverTip, { text: MODE_TIP2[provenance.mode] ?? GLOSSARY.reportMode, children: /* @__PURE__ */ jsx56(Badge10, { tone: "primary", children: provenance.mode }) }),
12534
- /* @__PURE__ */ jsx56(
12596
+ /* @__PURE__ */ jsx57(HoverTip, { text: MODE_TIP2[provenance.mode] ?? GLOSSARY.reportMode, children: /* @__PURE__ */ jsx57(Badge10, { tone: "primary", children: provenance.mode }) }),
12597
+ /* @__PURE__ */ jsx57(
12535
12598
  ReportActions,
12536
12599
  {
12600
+ artifactManifest: summary.artifactManifest,
12537
12601
  documentId: report._id,
12538
12602
  onDeleted: onBack,
12539
12603
  provenance,
@@ -12542,14 +12606,14 @@ function ReportDetail({
12542
12606
  )
12543
12607
  ] })
12544
12608
  ] }),
12545
- currentTab === "overview" && /* @__PURE__ */ jsx56(
12609
+ currentTab === "overview" && /* @__PURE__ */ jsx57(
12546
12610
  TabPanel,
12547
12611
  {
12548
12612
  "aria-labelledby": "tab-overview",
12549
12613
  hidden: currentTab !== "overview",
12550
12614
  id: "panel-overview",
12551
12615
  children: /* @__PURE__ */ jsxs41(Stack32, { space: 5, children: [
12552
- /* @__PURE__ */ jsx56(
12616
+ /* @__PURE__ */ jsx57(
12553
12617
  DiagnosticsOverview,
12554
12618
  {
12555
12619
  comparison,
@@ -12560,20 +12624,20 @@ function ReportDetail({
12560
12624
  totalTests
12561
12625
  }
12562
12626
  ),
12563
- /* @__PURE__ */ jsx56(CostLatencyPanel, { testResults: summary.testResults }),
12564
- /* @__PURE__ */ jsx56(
12627
+ /* @__PURE__ */ jsx57(CostLatencyPanel, { testResults: summary.testResults }),
12628
+ /* @__PURE__ */ jsx57(
12565
12629
  LineageCard,
12566
12630
  {
12567
12631
  provenance,
12568
12632
  reportId: report.reportId
12569
12633
  }
12570
12634
  ),
12571
- /* @__PURE__ */ jsx56(ProvenanceCard, { provenance }),
12572
- /* @__PURE__ */ jsx56(PipelineExecutionPanel, {})
12635
+ /* @__PURE__ */ jsx57(ProvenanceCard, { provenance }),
12636
+ /* @__PURE__ */ jsx57(PipelineExecutionPanel, {})
12573
12637
  ] })
12574
12638
  }
12575
12639
  ),
12576
- currentTab === "diagnostics" && hasDiagnostics && /* @__PURE__ */ jsx56(
12640
+ currentTab === "diagnostics" && hasDiagnostics && /* @__PURE__ */ jsx57(
12577
12641
  DiagnosticsPanel,
12578
12642
  {
12579
12643
  artifactCache,
@@ -12589,13 +12653,13 @@ function ReportDetail({
12589
12653
  testResults: summary.testResults
12590
12654
  }
12591
12655
  ),
12592
- currentTab === "activity" && hasAgentActivity && /* @__PURE__ */ jsx56(
12656
+ currentTab === "activity" && hasAgentActivity && /* @__PURE__ */ jsx57(
12593
12657
  TabPanel,
12594
12658
  {
12595
12659
  "aria-labelledby": "tab-activity",
12596
12660
  hidden: currentTab !== "activity",
12597
12661
  id: "panel-activity",
12598
- children: /* @__PURE__ */ jsx56(
12662
+ children: /* @__PURE__ */ jsx57(
12599
12663
  AgentBehaviorCard,
12600
12664
  {
12601
12665
  agentBehavior: summary.agentBehavior,
@@ -12633,8 +12697,8 @@ function DiagnosticsPanel({
12633
12697
  const issueCount = scores.filter((s) => s.totalScore < SCORE_CAUTION).length + scores.filter((s) => s.negativeDocLift).length + scores.filter(
12634
12698
  (s) => s.infrastructureEfficiency != null && s.infrastructureEfficiency < EFFICIENCY_CAUTION && !s.invertedRetrievalGap
12635
12699
  ).length;
12636
- return /* @__PURE__ */ jsx56(TabPanel, { "aria-labelledby": "tab-diagnostics", id: "panel-diagnostics", children: /* @__PURE__ */ jsxs41(Stack32, { space: 4, children: [
12637
- /* @__PURE__ */ jsx56(
12700
+ return /* @__PURE__ */ jsx57(TabPanel, { "aria-labelledby": "tab-diagnostics", id: "panel-diagnostics", children: /* @__PURE__ */ jsxs41(Stack32, { space: 4, children: [
12701
+ /* @__PURE__ */ jsx57(
12638
12702
  Flex30,
12639
12703
  {
12640
12704
  align: "center",
@@ -12664,7 +12728,7 @@ function DiagnosticsPanel({
12664
12728
  type: "button",
12665
12729
  children: [
12666
12730
  tab.label,
12667
- tab.id === "issues" && issueCount > 0 && /* @__PURE__ */ jsx56(
12731
+ tab.id === "issues" && issueCount > 0 && /* @__PURE__ */ jsx57(
12668
12732
  "span",
12669
12733
  {
12670
12734
  style: {
@@ -12684,7 +12748,7 @@ function DiagnosticsPanel({
12684
12748
  ))
12685
12749
  }
12686
12750
  ),
12687
- subTab === "strengths" && /* @__PURE__ */ jsx56(
12751
+ subTab === "strengths" && /* @__PURE__ */ jsx57(
12688
12752
  StrengthsList,
12689
12753
  {
12690
12754
  comparison,
@@ -12694,7 +12758,7 @@ function DiagnosticsPanel({
12694
12758
  }
12695
12759
  ),
12696
12760
  subTab === "issues" && /* @__PURE__ */ jsxs41(Stack32, { space: 5, children: [
12697
- /* @__PURE__ */ jsx56(
12761
+ /* @__PURE__ */ jsx57(
12698
12762
  WeaknessesList,
12699
12763
  {
12700
12764
  comparison,
@@ -12703,8 +12767,8 @@ function DiagnosticsPanel({
12703
12767
  scores
12704
12768
  }
12705
12769
  ),
12706
- FEATURE_FLAGS.showFailureModes.enabled && /* @__PURE__ */ jsx56(FailureModesPanel, { failureModes }),
12707
- judgments && judgments.length > 0 && /* @__PURE__ */ jsx56(
12770
+ FEATURE_FLAGS.showFailureModes.enabled && /* @__PURE__ */ jsx57(FailureModesPanel, { failureModes }),
12771
+ judgments && judgments.length > 0 && /* @__PURE__ */ jsx57(
12708
12772
  JudgmentList,
12709
12773
  {
12710
12774
  artifactCache,
@@ -12740,17 +12804,17 @@ function getDisabledTabTooltip(tabId, summary) {
12740
12804
  if (!summary) return null;
12741
12805
  switch (tabId) {
12742
12806
  case "diagnostics":
12743
- return /* @__PURE__ */ jsx56(Text42, { muted: true, size: 2, children: "No diagnostic data available. Diagnostics require at least one scored feature area." });
12807
+ return /* @__PURE__ */ jsx57(Text42, { muted: true, size: 2, children: "No diagnostic data available. Diagnostics require at least one scored feature area." });
12744
12808
  case "activity":
12745
12809
  return summary.evaluationMode === "baseline" ? /* @__PURE__ */ jsxs41(Text42, { muted: true, size: 2, children: [
12746
12810
  "Not available for baseline-only evaluations. Run with",
12747
12811
  " ",
12748
- /* @__PURE__ */ jsx56("code", { style: inlineCodeStyle, children: "--mode full" }),
12812
+ /* @__PURE__ */ jsx57("code", { style: inlineCodeStyle, children: "--mode full" }),
12749
12813
  " or",
12750
12814
  " ",
12751
- /* @__PURE__ */ jsx56("code", { style: inlineCodeStyle, children: "--mode agentic" }),
12815
+ /* @__PURE__ */ jsx57("code", { style: inlineCodeStyle, children: "--mode agentic" }),
12752
12816
  " to capture agent browsing behavior."
12753
- ] }) : /* @__PURE__ */ jsx56(Text42, { muted: true, size: 2, children: "No agent activity data was recorded for this evaluation." });
12817
+ ] }) : /* @__PURE__ */ jsx57(Text42, { muted: true, size: 2, children: "No agent activity data was recorded for this evaluation." });
12754
12818
  default:
12755
12819
  return null;
12756
12820
  }
@@ -12759,13 +12823,25 @@ function getDisabledTabTooltip(tabId, summary) {
12759
12823
  // src/components/report-detail/AreaScoreRow.tsx
12760
12824
  import { WarningOutlineIcon as WarningOutlineIcon4 } from "@sanity/icons";
12761
12825
  import { Box as Box30, Flex as Flex31, Stack as Stack33, Text as Text43 } from "@sanity/ui";
12762
- import { jsx as jsx57, jsxs as jsxs42 } from "react/jsx-runtime";
12826
+ import { jsx as jsx58, jsxs as jsxs42 } from "react/jsx-runtime";
12763
12827
 
12764
12828
  // src/components/report-detail/AreaScoreTable.tsx
12765
12829
  import React4 from "react";
12766
12830
  import { Card as Card19, Stack as Stack34, Text as Text45 } from "@sanity/ui";
12767
12831
 
12768
12832
  // src/lib/scoring.ts
12833
+ var TONE_MAP = {
12834
+ good: "positive",
12835
+ warning: "caution",
12836
+ "needs-work": "default",
12837
+ critical: "critical"
12838
+ };
12839
+ function gradeTone(grade) {
12840
+ return TONE_MAP[grade];
12841
+ }
12842
+ function scoreTone(score) {
12843
+ return gradeTone(scoreGrade(Math.round(score)));
12844
+ }
12769
12845
  var HEX_MAP = {
12770
12846
  good: "#2ecc71",
12771
12847
  warning: "#f1c40f",
@@ -12781,32 +12857,32 @@ function scoreHex(score) {
12781
12857
 
12782
12858
  // src/components/primitives/ScoreCell.tsx
12783
12859
  import { Card as Card18, Text as Text44 } from "@sanity/ui";
12784
- import { jsx as jsx58 } from "react/jsx-runtime";
12860
+ import { jsx as jsx59 } from "react/jsx-runtime";
12785
12861
 
12786
12862
  // src/components/report-detail/AreaScoreTable.tsx
12787
- import { jsx as jsx59, jsxs as jsxs43 } from "react/jsx-runtime";
12863
+ import { jsx as jsx60, jsxs as jsxs43 } from "react/jsx-runtime";
12788
12864
 
12789
12865
  // src/components/report-detail/AutoComparisonCard.tsx
12790
12866
  import { Badge as Badge11, Box as Box31, Card as Card20, Flex as Flex32, Grid as Grid5, Stack as Stack35, Text as Text46, Tooltip as Tooltip11 } from "@sanity/ui";
12791
- import { jsx as jsx60, jsxs as jsxs44 } from "react/jsx-runtime";
12867
+ import { jsx as jsx61, jsxs as jsxs44 } from "react/jsx-runtime";
12792
12868
 
12793
12869
  // src/components/report-detail/OverviewStats.tsx
12794
12870
  import { Grid as Grid6 } from "@sanity/ui";
12795
- import { jsx as jsx61, jsxs as jsxs45 } from "react/jsx-runtime";
12871
+ import { jsx as jsx62, jsxs as jsxs45 } from "react/jsx-runtime";
12796
12872
 
12797
12873
  // src/components/report-detail/RecommendationsSection.tsx
12798
12874
  import { BoltIcon as BoltIcon2 } from "@sanity/icons";
12799
12875
  import { Box as Box32, Flex as Flex33, Stack as Stack36, Text as Text47 } from "@sanity/ui";
12800
- import { jsx as jsx62, jsxs as jsxs46 } from "react/jsx-runtime";
12876
+ import { jsx as jsx63, jsxs as jsxs46 } from "react/jsx-runtime";
12801
12877
 
12802
12878
  // src/components/report-detail/ThreeLayerTable.tsx
12803
12879
  import React5 from "react";
12804
12880
  import { Badge as Badge12, Card as Card21, Flex as Flex34, Stack as Stack37, Text as Text48 } from "@sanity/ui";
12805
- import { jsx as jsx63, jsxs as jsxs47 } from "react/jsx-runtime";
12881
+ import { jsx as jsx64, jsxs as jsxs47 } from "react/jsx-runtime";
12806
12882
 
12807
12883
  // src/components/report-detail/JudgmentDetailDrawerOutlet.tsx
12808
12884
  import { Card as Card22 } from "@sanity/ui";
12809
- import { useCallback as useCallback37, useEffect as useEffect15, useRef as useRef8, useState as useState29 } from "react";
12885
+ import { useCallback as useCallback38, useEffect as useEffect15, useRef as useRef8, useState as useState29 } from "react";
12810
12886
 
12811
12887
  // src/components/report-detail/JudgmentDetailDrawer.tsx
12812
12888
  import { useEffect as useEffect14, useState as useState28 } from "react";
@@ -12822,7 +12898,7 @@ import {
12822
12898
  Text as Text49,
12823
12899
  Tooltip as Tooltip12
12824
12900
  } from "@sanity/ui";
12825
- import { jsx as jsx64, jsxs as jsxs48 } from "react/jsx-runtime";
12901
+ import { jsx as jsx65, jsxs as jsxs48 } from "react/jsx-runtime";
12826
12902
  var HEADER_STYLE = {
12827
12903
  borderBottom: "1px solid var(--card-border-color)"
12828
12904
  };
@@ -12861,7 +12937,7 @@ function DocBadge({
12861
12937
  const [hovered, setHovered] = useState28(false);
12862
12938
  const isLinked = Boolean(doc.documentId);
12863
12939
  const tooltipLabel = isLinked ? `Edit "${doc.title || doc.slug}"` : doc.title || doc.slug;
12864
- const badge = /* @__PURE__ */ jsx64(
12940
+ const badge = /* @__PURE__ */ jsx65(
12865
12941
  "span",
12866
12942
  {
12867
12943
  style: {
@@ -12874,13 +12950,13 @@ function DocBadge({
12874
12950
  children: doc.slug
12875
12951
  }
12876
12952
  );
12877
- return /* @__PURE__ */ jsx64(
12953
+ return /* @__PURE__ */ jsx65(
12878
12954
  Tooltip12,
12879
12955
  {
12880
- content: /* @__PURE__ */ jsx64(Box33, { padding: 2, children: /* @__PURE__ */ jsx64(Text49, { size: 2, children: tooltipLabel }) }),
12956
+ content: /* @__PURE__ */ jsx65(Box33, { padding: 2, children: /* @__PURE__ */ jsx65(Text49, { size: 2, children: tooltipLabel }) }),
12881
12957
  placement: "bottom",
12882
12958
  portal: true,
12883
- children: isLinked ? /* @__PURE__ */ jsx64(
12959
+ children: isLinked ? /* @__PURE__ */ jsx65(
12884
12960
  "a",
12885
12961
  {
12886
12962
  href: `/intent/edit/id=${doc.documentId}`,
@@ -12895,7 +12971,7 @@ function DocBadge({
12895
12971
  },
12896
12972
  children: badge
12897
12973
  }
12898
- ) : /* @__PURE__ */ jsx64("span", { children: badge })
12974
+ ) : /* @__PURE__ */ jsx65("span", { children: badge })
12899
12975
  }
12900
12976
  );
12901
12977
  }
@@ -12968,7 +13044,7 @@ function JudgmentDetailDrawer({
12968
13044
  role: "dialog",
12969
13045
  style: { flex: 1, height: "100%", minHeight: 0, overflow: "hidden" },
12970
13046
  children: [
12971
- /* @__PURE__ */ jsx64(
13047
+ /* @__PURE__ */ jsx65(
12972
13048
  "div",
12973
13049
  {
12974
13050
  "aria-hidden": true,
@@ -12984,7 +13060,7 @@ function JudgmentDetailDrawer({
12984
13060
  /* @__PURE__ */ jsxs48(Flex35, { align: "flex-start", gap: 2, padding: 4, style: HEADER_STYLE, children: [
12985
13061
  /* @__PURE__ */ jsxs48(Stack38, { flex: 1, space: 2, children: [
12986
13062
  /* @__PURE__ */ jsxs48(Flex35, { align: "center", gap: 2, wrap: "wrap", children: [
12987
- /* @__PURE__ */ jsx64(
13063
+ /* @__PURE__ */ jsx65(
12988
13064
  "span",
12989
13065
  {
12990
13066
  style: {
@@ -12999,7 +13075,7 @@ function JudgmentDetailDrawer({
12999
13075
  children: judgment.score
13000
13076
  }
13001
13077
  ),
13002
- /* @__PURE__ */ jsx64(
13078
+ /* @__PURE__ */ jsx65(
13003
13079
  "span",
13004
13080
  {
13005
13081
  style: {
@@ -13012,13 +13088,13 @@ function JudgmentDetailDrawer({
13012
13088
  children: dimLabel
13013
13089
  }
13014
13090
  ),
13015
- /* @__PURE__ */ jsx64(
13091
+ /* @__PURE__ */ jsx65(
13016
13092
  Tooltip12,
13017
13093
  {
13018
- content: /* @__PURE__ */ jsx64(Box33, { padding: 2, children: /* @__PURE__ */ jsx64(Text49, { size: 1, children: judgment.modelId }) }),
13094
+ content: /* @__PURE__ */ jsx65(Box33, { padding: 2, children: /* @__PURE__ */ jsx65(Text49, { size: 1, children: judgment.modelId }) }),
13019
13095
  placement: "bottom",
13020
13096
  portal: true,
13021
- children: /* @__PURE__ */ jsx64(
13097
+ children: /* @__PURE__ */ jsx65(
13022
13098
  "span",
13023
13099
  {
13024
13100
  style: {
@@ -13035,7 +13111,7 @@ function JudgmentDetailDrawer({
13035
13111
  )
13036
13112
  }
13037
13113
  ),
13038
- (testResult?.latencyMs != null || testResult?.cost != null && testResult.cost > 0) && /* @__PURE__ */ jsx64(
13114
+ (testResult?.latencyMs != null || testResult?.cost != null && testResult.cost > 0) && /* @__PURE__ */ jsx65(
13039
13115
  "span",
13040
13116
  {
13041
13117
  "aria-hidden": true,
@@ -13047,10 +13123,10 @@ function JudgmentDetailDrawer({
13047
13123
  }
13048
13124
  }
13049
13125
  ),
13050
- testResult?.latencyMs != null && /* @__PURE__ */ jsx64(
13126
+ testResult?.latencyMs != null && /* @__PURE__ */ jsx65(
13051
13127
  Tooltip12,
13052
13128
  {
13053
- content: /* @__PURE__ */ jsx64(Box33, { padding: 2, children: /* @__PURE__ */ jsx64(Text49, { size: 1, children: "End-to-end generation latency for this model call." }) }),
13129
+ content: /* @__PURE__ */ jsx65(Box33, { padding: 2, children: /* @__PURE__ */ jsx65(Text49, { size: 1, children: "End-to-end generation latency for this model call." }) }),
13054
13130
  placement: "bottom",
13055
13131
  portal: true,
13056
13132
  children: /* @__PURE__ */ jsxs48(Text49, { muted: true, size: 1, children: [
@@ -13059,10 +13135,10 @@ function JudgmentDetailDrawer({
13059
13135
  ] })
13060
13136
  }
13061
13137
  ),
13062
- testResult?.cost != null && testResult.cost > 0 && /* @__PURE__ */ jsx64(
13138
+ testResult?.cost != null && testResult.cost > 0 && /* @__PURE__ */ jsx65(
13063
13139
  Tooltip12,
13064
13140
  {
13065
- content: /* @__PURE__ */ jsx64(Box33, { padding: 2, children: /* @__PURE__ */ jsx64(Text49, { size: 1, children: "Provider-reported cost for this model call." }) }),
13141
+ content: /* @__PURE__ */ jsx65(Box33, { padding: 2, children: /* @__PURE__ */ jsx65(Text49, { size: 1, children: "Provider-reported cost for this model call." }) }),
13066
13142
  placement: "bottom",
13067
13143
  portal: true,
13068
13144
  children: /* @__PURE__ */ jsxs48(Text49, { muted: true, size: 1, children: [
@@ -13073,12 +13149,12 @@ function JudgmentDetailDrawer({
13073
13149
  )
13074
13150
  ] }),
13075
13151
  /* @__PURE__ */ jsxs48(Flex35, { align: "center", gap: 2, wrap: "wrap", children: [
13076
- /* @__PURE__ */ jsx64(Text49, { size: 2, weight: "medium", children: taskName }),
13077
- /* @__PURE__ */ jsx64(VariantBadge, { variant })
13152
+ /* @__PURE__ */ jsx65(Text49, { size: 2, weight: "medium", children: taskName }),
13153
+ /* @__PURE__ */ jsx65(VariantBadge, { variant })
13078
13154
  ] })
13079
13155
  ] }),
13080
13156
  /* @__PURE__ */ jsxs48(Flex35, { align: "center", gap: 1, children: [
13081
- /* @__PURE__ */ jsx64(
13157
+ /* @__PURE__ */ jsx65(
13082
13158
  "span",
13083
13159
  {
13084
13160
  style: {
@@ -13096,7 +13172,7 @@ function JudgmentDetailDrawer({
13096
13172
  children: "Esc"
13097
13173
  }
13098
13174
  ),
13099
- /* @__PURE__ */ jsx64(
13175
+ /* @__PURE__ */ jsx65(
13100
13176
  Button12,
13101
13177
  {
13102
13178
  "aria-label": "Close (Esc)",
@@ -13119,8 +13195,8 @@ function JudgmentDetailDrawer({
13119
13195
  paddingY: 2,
13120
13196
  style: TAB_BAR_STYLE,
13121
13197
  children: [
13122
- /* @__PURE__ */ jsx64(Box33, { flex: 1, style: { minWidth: 0 }, children: /* @__PURE__ */ jsxs48(TabList2, { space: 2, children: [
13123
- /* @__PURE__ */ jsx64(
13198
+ /* @__PURE__ */ jsx65(Box33, { flex: 1, style: { minWidth: 0 }, children: /* @__PURE__ */ jsxs48(TabList2, { space: 2, children: [
13199
+ /* @__PURE__ */ jsx65(
13124
13200
  Tab2,
13125
13201
  {
13126
13202
  "aria-controls": "judgment-panel-reasoning",
@@ -13130,7 +13206,7 @@ function JudgmentDetailDrawer({
13130
13206
  selected: tab === "reasoning"
13131
13207
  }
13132
13208
  ),
13133
- hasOutputTab && /* @__PURE__ */ jsx64(
13209
+ hasOutputTab && /* @__PURE__ */ jsx65(
13134
13210
  Tab2,
13135
13211
  {
13136
13212
  "aria-controls": "judgment-panel-output",
@@ -13141,7 +13217,7 @@ function JudgmentDetailDrawer({
13141
13217
  }
13142
13218
  )
13143
13219
  ] }) }),
13144
- /* @__PURE__ */ jsx64(
13220
+ /* @__PURE__ */ jsx65(
13145
13221
  JudgmentActions,
13146
13222
  {
13147
13223
  onShowPrompts: onShowPrompts ? () => onShowPrompts(judgment) : void 0
@@ -13151,14 +13227,14 @@ function JudgmentDetailDrawer({
13151
13227
  }
13152
13228
  ),
13153
13229
  /* @__PURE__ */ jsxs48(Box33, { padding: 4, style: CONTENT_STYLE, children: [
13154
- /* @__PURE__ */ jsx64(
13230
+ /* @__PURE__ */ jsx65(
13155
13231
  TabPanel2,
13156
13232
  {
13157
13233
  "aria-labelledby": "judgment-tab-reasoning",
13158
13234
  hidden: tab !== "reasoning",
13159
13235
  id: "judgment-panel-reasoning",
13160
13236
  children: /* @__PURE__ */ jsxs48(Box33, { style: COPYABLE_BLOCK_STYLE, children: [
13161
- /* @__PURE__ */ jsx64(Box33, { style: COPY_BUTTON_SLOT_STYLE, children: /* @__PURE__ */ jsx64(
13237
+ /* @__PURE__ */ jsx65(Box33, { style: COPY_BUTTON_SLOT_STYLE, children: /* @__PURE__ */ jsx65(
13162
13238
  CopyButton,
13163
13239
  {
13164
13240
  copiedLabel: "Reasoning copied",
@@ -13166,8 +13242,8 @@ function JudgmentDetailDrawer({
13166
13242
  text: reasoningText
13167
13243
  }
13168
13244
  ) }),
13169
- /* @__PURE__ */ jsx64(Markdown, { content: reasoningText }),
13170
- reasoningIsPreview && /* @__PURE__ */ jsx64(Text49, { muted: true, size: 1, style: { marginTop: 8 }, children: fullStatus === "loading" ? "Loading full reasoning\u2026" : "Showing preview (280 chars). Full reasoning not yet loaded." })
13245
+ /* @__PURE__ */ jsx65(Markdown, { content: reasoningText }),
13246
+ reasoningIsPreview && /* @__PURE__ */ jsx65(Text49, { muted: true, size: 1, style: { marginTop: 8 }, children: fullStatus === "loading" ? "Loading full reasoning\u2026" : "Showing preview (280 chars). Full reasoning not yet loaded." })
13171
13247
  ] })
13172
13248
  }
13173
13249
  ),
@@ -13178,14 +13254,14 @@ function JudgmentDetailDrawer({
13178
13254
  hidden: tab !== "output",
13179
13255
  id: "judgment-panel-output",
13180
13256
  children: [
13181
- !resolvedOutput && fetchInFlight && /* @__PURE__ */ jsx64(Text49, { muted: true, size: 1, children: "Fetching model output\u2026" }),
13257
+ !resolvedOutput && fetchInFlight && /* @__PURE__ */ jsx65(Text49, { muted: true, size: 1, children: "Fetching model output\u2026" }),
13182
13258
  !resolvedOutput && fetchFailed && /* @__PURE__ */ jsxs48(Text49, { muted: true, size: 1, style: { color: "#f87171" }, children: [
13183
13259
  "Failed to load model output",
13184
13260
  artifactCache?.error ? `: ${artifactCache.error}` : ""
13185
13261
  ] }),
13186
- !resolvedOutput && entryUnavailable && /* @__PURE__ */ jsx64(Text49, { muted: true, size: 1, children: "Model output not available for this entry." }),
13262
+ !resolvedOutput && entryUnavailable && /* @__PURE__ */ jsx65(Text49, { muted: true, size: 1, children: "Model output not available for this entry." }),
13187
13263
  resolvedOutput && /* @__PURE__ */ jsxs48(Box33, { style: COPYABLE_BLOCK_STYLE, children: [
13188
- /* @__PURE__ */ jsx64(Box33, { style: COPY_BUTTON_SLOT_STYLE, children: /* @__PURE__ */ jsx64(
13264
+ /* @__PURE__ */ jsx65(Box33, { style: COPY_BUTTON_SLOT_STYLE, children: /* @__PURE__ */ jsx65(
13189
13265
  CopyButton,
13190
13266
  {
13191
13267
  copiedLabel: "Output copied",
@@ -13193,15 +13269,15 @@ function JudgmentDetailDrawer({
13193
13269
  text: resolvedOutput
13194
13270
  }
13195
13271
  ) }),
13196
- /* @__PURE__ */ jsx64(Markdown, { content: resolvedOutput })
13272
+ /* @__PURE__ */ jsx65(Markdown, { content: resolvedOutput })
13197
13273
  ] })
13198
13274
  ]
13199
13275
  }
13200
13276
  )
13201
13277
  ] }),
13202
- judgment.canonicalDocs && judgment.canonicalDocs.length > 0 && /* @__PURE__ */ jsx64(Box33, { padding: 4, style: RELATED_DOCS_STYLE, children: /* @__PURE__ */ jsxs48(Flex35, { align: "center", gap: 2, wrap: "wrap", children: [
13203
- /* @__PURE__ */ jsx64("span", { style: SECTION_LABEL_STYLE, children: "Related docs" }),
13204
- judgment.canonicalDocs.map((doc) => /* @__PURE__ */ jsx64(DocBadge, { doc }, doc.slug))
13278
+ judgment.canonicalDocs && judgment.canonicalDocs.length > 0 && /* @__PURE__ */ jsx65(Box33, { padding: 4, style: RELATED_DOCS_STYLE, children: /* @__PURE__ */ jsxs48(Flex35, { align: "center", gap: 2, wrap: "wrap", children: [
13279
+ /* @__PURE__ */ jsx65("span", { style: SECTION_LABEL_STYLE, children: "Related docs" }),
13280
+ judgment.canonicalDocs.map((doc) => /* @__PURE__ */ jsx65(DocBadge, { doc }, doc.slug))
13205
13281
  ] }) })
13206
13282
  ]
13207
13283
  }
@@ -13209,7 +13285,7 @@ function JudgmentDetailDrawer({
13209
13285
  }
13210
13286
 
13211
13287
  // src/components/report-detail/JudgmentDetailDrawerOutlet.tsx
13212
- import { jsx as jsx65, jsxs as jsxs49 } from "react/jsx-runtime";
13288
+ import { jsx as jsx66, jsxs as jsxs49 } from "react/jsx-runtime";
13213
13289
  var MIN_WIDTH2 = 480;
13214
13290
  var MAX_WIDTH2 = 900;
13215
13291
  var OVERLAY_BREAKPOINT2 = 1024;
@@ -13236,7 +13312,7 @@ function useResizable2(defaultWidth) {
13236
13312
  const dragging = useRef8(false);
13237
13313
  const startX = useRef8(0);
13238
13314
  const startWidth = useRef8(0);
13239
- const handleMouseDown = useCallback37(
13315
+ const handleMouseDown = useCallback38(
13240
13316
  (e) => {
13241
13317
  e.preventDefault();
13242
13318
  dragging.current = true;
@@ -13305,7 +13381,7 @@ function JudgmentDetailDrawerOutlet({
13305
13381
  width
13306
13382
  },
13307
13383
  children: [
13308
- !isNarrow && /* @__PURE__ */ jsx65(
13384
+ !isNarrow && /* @__PURE__ */ jsx66(
13309
13385
  "div",
13310
13386
  {
13311
13387
  "aria-label": "Resize judgment drawer",
@@ -13330,7 +13406,7 @@ function JudgmentDetailDrawerOutlet({
13330
13406
  }
13331
13407
  }
13332
13408
  ),
13333
- /* @__PURE__ */ jsx65(
13409
+ /* @__PURE__ */ jsx66(
13334
13410
  Card22,
13335
13411
  {
13336
13412
  borderLeft: !isNarrow,
@@ -13340,7 +13416,7 @@ function JudgmentDetailDrawerOutlet({
13340
13416
  flexDirection: "column",
13341
13417
  overflow: "hidden"
13342
13418
  },
13343
- children: /* @__PURE__ */ jsx65(ReportArtifactProvider, { runId: active.runId, manifest: active.manifest, children: /* @__PURE__ */ jsx65(
13419
+ children: /* @__PURE__ */ jsx66(ReportArtifactProvider, { runId: active.runId, manifest: active.manifest, children: /* @__PURE__ */ jsx66(
13344
13420
  JudgmentDetailDrawer,
13345
13421
  {
13346
13422
  artifactCache: active.artifactCache,
@@ -13358,244 +13434,1158 @@ function JudgmentDetailDrawerOutlet({
13358
13434
  }
13359
13435
 
13360
13436
  // src/components/ScoreTimeline.tsx
13361
- import { Card as Card23, Flex as Flex36, Select as Select2, Stack as Stack39, Text as Text50 } from "@sanity/ui";
13362
- import { useCallback as useCallback38, useEffect as useEffect16, useMemo as useMemo17, useState as useState30 } from "react";
13363
- import { useClient as useClient13 } from "sanity";
13364
- import { jsx as jsx66, jsxs as jsxs50 } from "react/jsx-runtime";
13365
- var CHART_HEIGHT = 220;
13366
- var CHART_WIDTH = 800;
13367
- var PAD_BOTTOM = 30;
13368
- var PAD_LEFT = 40;
13369
- var PAD_RIGHT = 20;
13370
- var PAD_TOP = 20;
13371
- var PLOT_HEIGHT = CHART_HEIGHT - PAD_TOP - PAD_BOTTOM;
13372
- var PLOT_WIDTH = CHART_WIDTH - PAD_LEFT - PAD_RIGHT;
13373
- var Y_MAX = 100;
13374
- var Y_TICKS = [0, 25, 50, 75, 100];
13375
- var TIME_RANGES = [
13376
- { days: 7, label: "Last 7 days" },
13377
- { days: 30, label: "Last 30 days" },
13378
- { days: 90, label: "Last 90 days" },
13379
- { days: null, label: "All time" }
13437
+ import { Card as Card25, Flex as Flex38, Spinner, Stack as Stack41, Text as Text52 } from "@sanity/ui";
13438
+ import { useCallback as useCallback42, useMemo as useMemo19, useState as useState32 } from "react";
13439
+ import { useRouter as useRouter4 } from "sanity/router";
13440
+
13441
+ // src/components/timeline/TimelineChart.tsx
13442
+ import { Box as Box34, Card as Card23, Flex as Flex36, Stack as Stack39, Text as Text50 } from "@sanity/ui";
13443
+ import {
13444
+ useCallback as useCallback39,
13445
+ useEffect as useEffect16,
13446
+ useMemo as useMemo17,
13447
+ useRef as useRef9,
13448
+ useState as useState30
13449
+ } from "react";
13450
+
13451
+ // src/components/timeline/lib.ts
13452
+ var RANGE_OPTIONS = [
13453
+ { days: 7, label: "Last 7 days", value: "7d" },
13454
+ { days: 30, label: "Last 30 days", value: "30d" },
13455
+ { days: 90, label: "Last 90 days", value: "90d" },
13456
+ { days: 180, label: "Last 180 days", value: "180d" },
13457
+ { days: 365, label: "Last year", value: "365d" },
13458
+ { days: null, label: "All time", value: "all" }
13380
13459
  ];
13460
+ var DEFAULT_RANGE = "30d";
13461
+ function rangePresetToDays(preset) {
13462
+ const opt = RANGE_OPTIONS.find((r) => r.value === preset);
13463
+ if (!opt) throw new Error(`Unknown range preset: ${preset}`);
13464
+ return opt.days;
13465
+ }
13466
+ function isRangePreset(value) {
13467
+ return RANGE_OPTIONS.some((r) => r.value === value);
13468
+ }
13469
+ var GRANULARITY_OPTIONS = [
13470
+ { label: "All", value: "raw" },
13471
+ { label: "Daily average", value: "day" },
13472
+ { label: "Weekly average", value: "week" }
13473
+ ];
13474
+ var DEFAULT_GRANULARITY = "raw";
13475
+ function isGranularity(value) {
13476
+ return value === "raw" || value === "day" || value === "week";
13477
+ }
13381
13478
  function daysAgo(n) {
13382
13479
  const d = /* @__PURE__ */ new Date();
13383
13480
  d.setDate(d.getDate() - n);
13384
13481
  return d.toISOString();
13385
13482
  }
13386
- function formatDate(iso) {
13483
+ function formatDateShort(iso) {
13387
13484
  return new Date(iso).toLocaleDateString(void 0, {
13388
13485
  day: "numeric",
13389
13486
  month: "short"
13390
13487
  });
13391
13488
  }
13489
+ function formatDateTime(iso) {
13490
+ return new Date(iso).toLocaleString(void 0, {
13491
+ day: "numeric",
13492
+ hour: "2-digit",
13493
+ minute: "2-digit",
13494
+ month: "short",
13495
+ year: "numeric"
13496
+ });
13497
+ }
13498
+ function startOfDay(iso) {
13499
+ const d = new Date(iso);
13500
+ d.setUTCHours(0, 0, 0, 0);
13501
+ return d.toISOString();
13502
+ }
13503
+ function startOfWeek(iso) {
13504
+ const d = new Date(iso);
13505
+ d.setUTCHours(0, 0, 0, 0);
13506
+ const day = d.getUTCDay();
13507
+ const diff = (day + 6) % 7;
13508
+ d.setUTCDate(d.getUTCDate() - diff);
13509
+ return d.toISOString();
13510
+ }
13392
13511
  function scoreForPoint(point, area) {
13393
13512
  if (!area) return point.overall;
13394
13513
  const match = point.scores.find((s) => s.feature === area);
13395
13514
  return match?.totalScore ?? null;
13396
13515
  }
13397
- function ScoreTimeline({ mode = null, source = null }) {
13398
- const client = useClient13({ apiVersion: API_VERSION });
13399
- const [dataPoints, setDataPoints] = useState30([]);
13400
- const [loading, setLoading] = useState30(true);
13401
- const [rangeDays, setRangeDays] = useState30(30);
13402
- const [selectedArea, setSelectedArea] = useState30(null);
13403
- const areaNames = useMemo17(() => {
13404
- const names = /* @__PURE__ */ new Set();
13405
- for (const dp of dataPoints) {
13406
- for (const s of dp.scores) {
13407
- names.add(s.feature);
13408
- }
13516
+ function aggregate(points, area, granularity) {
13517
+ const scored = [];
13518
+ for (const dp of points) {
13519
+ const score = scoreForPoint(dp, area);
13520
+ if (score === null) continue;
13521
+ scored.push({ count: 1, date: dp.completedAt, score, source: dp });
13522
+ }
13523
+ if (granularity === "raw" || scored.length === 0) return scored;
13524
+ const bucketKey = granularity === "day" ? startOfDay : startOfWeek;
13525
+ const buckets = /* @__PURE__ */ new Map();
13526
+ for (const d of scored) {
13527
+ const key = bucketKey(d.date);
13528
+ const cur = buckets.get(key);
13529
+ if (cur) {
13530
+ cur.sum += d.score;
13531
+ cur.count += 1;
13532
+ if (d.date > cur.source.completedAt) cur.source = d.source;
13533
+ } else {
13534
+ buckets.set(key, { count: 1, source: d.source, sum: d.score });
13409
13535
  }
13410
- return Array.from(names).sort();
13411
- }, [dataPoints]);
13412
- const fetchData = useCallback38(async () => {
13413
- setLoading(true);
13414
- try {
13415
- const startDate = rangeDays ? daysAgo(rangeDays) : "1970-01-01T00:00:00Z";
13416
- const results = await client.fetch(
13417
- scoreTimelineQuery,
13418
- { mode, source, startDate }
13419
- );
13420
- setDataPoints(results ?? []);
13421
- } catch {
13422
- setDataPoints([]);
13423
- } finally {
13424
- setLoading(false);
13536
+ }
13537
+ return Array.from(buckets.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([date, { count, source, sum }]) => ({
13538
+ count,
13539
+ date,
13540
+ score: sum / count,
13541
+ source
13542
+ }));
13543
+ }
13544
+ function uniqueSorted(items, extract) {
13545
+ const set2 = /* @__PURE__ */ new Set();
13546
+ for (const item of items) {
13547
+ for (const v of extract(item)) {
13548
+ if (v) set2.add(v);
13549
+ }
13550
+ }
13551
+ return Array.from(set2).sort();
13552
+ }
13553
+ function computeStats(points, window2 = 5) {
13554
+ if (points.length === 0) {
13555
+ return {
13556
+ count: 0,
13557
+ delta: null,
13558
+ first: null,
13559
+ last: null,
13560
+ max: null,
13561
+ mean: null,
13562
+ median: null,
13563
+ min: null,
13564
+ movingAverage: [],
13565
+ stdev: null,
13566
+ trend: "flat"
13567
+ };
13568
+ }
13569
+ const scores = points.map((p) => p.score);
13570
+ const sum = scores.reduce((a, b) => a + b, 0);
13571
+ const mean = sum / scores.length;
13572
+ const sorted = [...scores].sort((a, b) => a - b);
13573
+ const median2 = sorted.length % 2 === 0 ? (sorted[sorted.length / 2 - 1] + sorted[sorted.length / 2]) / 2 : sorted[(sorted.length - 1) / 2];
13574
+ let minIdx = 0;
13575
+ let maxIdx = 0;
13576
+ for (let i = 1; i < points.length; i++) {
13577
+ if (points[i].score < points[minIdx].score) minIdx = i;
13578
+ if (points[i].score > points[maxIdx].score) maxIdx = i;
13579
+ }
13580
+ const variance = scores.reduce((acc, x) => acc + (x - mean) ** 2, 0) / scores.length;
13581
+ const stdev = Math.sqrt(variance);
13582
+ const first = points[0];
13583
+ const last = points[points.length - 1];
13584
+ const delta = points.length > 1 ? last.score - first.score : 0;
13585
+ const trend = classifyTrend(delta);
13586
+ return {
13587
+ count: points.length,
13588
+ delta,
13589
+ first,
13590
+ last,
13591
+ max: points[maxIdx],
13592
+ mean,
13593
+ median: median2,
13594
+ min: points[minIdx],
13595
+ movingAverage: rollingMean(scores, window2),
13596
+ stdev,
13597
+ trend
13598
+ };
13599
+ }
13600
+ function classifyTrend(delta) {
13601
+ if (Math.abs(delta) < 1.5) return "flat";
13602
+ return delta > 0 ? "up" : "down";
13603
+ }
13604
+ function rollingMean(values, window2) {
13605
+ if (values.length === 0) return [];
13606
+ const w = Math.max(1, Math.min(window2, values.length));
13607
+ const out = [];
13608
+ let runningSum = 0;
13609
+ const queue = [];
13610
+ for (const v of values) {
13611
+ queue.push(v);
13612
+ runningSum += v;
13613
+ if (queue.length > w) {
13614
+ runningSum -= queue.shift();
13425
13615
  }
13426
- }, [client, mode, rangeDays, source]);
13616
+ out.push(runningSum / queue.length);
13617
+ }
13618
+ return out;
13619
+ }
13620
+ var CSV_HEADER = [
13621
+ "completedAt",
13622
+ "reportId",
13623
+ "title",
13624
+ "tag",
13625
+ "mode",
13626
+ "source",
13627
+ "trigger",
13628
+ "overall",
13629
+ "selectedAreaScore",
13630
+ "actualScore",
13631
+ "durationMs"
13632
+ ];
13633
+ function csvEscape(value) {
13634
+ if (value == null) return "";
13635
+ const s = String(value);
13636
+ if (/[",\n\r]/.test(s)) return `"${s.replaceAll('"', '""')}"`;
13637
+ return s;
13638
+ }
13639
+ function toCsv(points, selectedArea) {
13640
+ const rows = [CSV_HEADER.join(",")];
13641
+ for (const p of points) {
13642
+ const areaScore = scoreForPoint(p, selectedArea);
13643
+ rows.push(
13644
+ [
13645
+ p.completedAt,
13646
+ p.reportId ?? p._id,
13647
+ p.title ?? "",
13648
+ p.tag ?? "",
13649
+ p.mode,
13650
+ p.source,
13651
+ p.trigger ?? "",
13652
+ p.overall ?? "",
13653
+ areaScore ?? "",
13654
+ p.actualScore ?? "",
13655
+ p.durationMs ?? ""
13656
+ ].map(csvEscape).join(",")
13657
+ );
13658
+ }
13659
+ return rows.join("\n") + "\n";
13660
+ }
13661
+ function downloadCsv(content, filename) {
13662
+ if (typeof document === "undefined") return;
13663
+ const blob = new Blob([content], { type: "text/csv;charset=utf-8" });
13664
+ const url = URL.createObjectURL(blob);
13665
+ const link = document.createElement("a");
13666
+ link.href = url;
13667
+ link.download = filename;
13668
+ document.body.append(link);
13669
+ link.click();
13670
+ link.remove();
13671
+ setTimeout(() => URL.revokeObjectURL(url), 0);
13672
+ }
13673
+ async function copyTextToClipboard(text) {
13674
+ if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
13675
+ return false;
13676
+ }
13677
+ try {
13678
+ await navigator.clipboard.writeText(text);
13679
+ return true;
13680
+ } catch {
13681
+ return false;
13682
+ }
13683
+ }
13684
+ var TIMELINE_DATA_START_DATE = "2026-04-15T00:00:00Z";
13685
+ function effectiveStartDate(rangeDays, floor = TIMELINE_DATA_START_DATE) {
13686
+ const rangeStart = rangeDays ? daysAgo(rangeDays) : "1970-01-01T00:00:00Z";
13687
+ if (!floor) return rangeStart;
13688
+ return rangeStart > floor ? rangeStart : floor;
13689
+ }
13690
+
13691
+ // src/components/timeline/TimelineChart.tsx
13692
+ import { jsx as jsx67, jsxs as jsxs50 } from "react/jsx-runtime";
13693
+ var CHART_HEIGHT = 280;
13694
+ var PAD_BOTTOM = 36;
13695
+ var PAD_LEFT = 44;
13696
+ var PAD_RIGHT = 16;
13697
+ var PAD_TOP = 16;
13698
+ var Y_MAX = 100;
13699
+ var Y_TICKS = [0, 25, 50, 75, 100];
13700
+ var NOISE_BAND = 3;
13701
+ var X_LABEL_TARGET = 6;
13702
+ function TimelineChart({
13703
+ movingAverage,
13704
+ onSelectPoint,
13705
+ points,
13706
+ showMovingAverage
13707
+ }) {
13708
+ const containerRef = useRef9(null);
13709
+ const [width, setWidth] = useState30(800);
13710
+ const [hoverIdx, setHoverIdx] = useState30(null);
13711
+ const [focusIdx, setFocusIdx] = useState30(null);
13427
13712
  useEffect16(() => {
13428
- void fetchData();
13429
- }, [fetchData]);
13430
- const chartPoints = useMemo17(() => {
13431
- const pts = [];
13432
- const scored = dataPoints.map((dp) => ({
13433
- date: dp.completedAt,
13434
- score: scoreForPoint(dp, selectedArea)
13435
- })).filter((d) => d.score !== null);
13436
- if (scored.length === 0) return pts;
13437
- scored.forEach((d, i) => {
13438
- const x = PAD_LEFT + (scored.length === 1 ? PLOT_WIDTH / 2 : i / (scored.length - 1) * PLOT_WIDTH);
13439
- const y = PAD_TOP + PLOT_HEIGHT - d.score / Y_MAX * PLOT_HEIGHT;
13440
- pts.push({ date: d.date, score: d.score, x, y });
13713
+ const node = containerRef.current;
13714
+ if (!node || typeof ResizeObserver === "undefined") return;
13715
+ const ro = new ResizeObserver((entries) => {
13716
+ const entry = entries[0];
13717
+ if (!entry) return;
13718
+ const w = Math.max(320, Math.floor(entry.contentRect.width));
13719
+ setWidth(w);
13441
13720
  });
13442
- return pts;
13443
- }, [dataPoints, selectedArea]);
13721
+ ro.observe(node);
13722
+ return () => ro.disconnect();
13723
+ }, []);
13724
+ const plotWidth = width - PAD_LEFT - PAD_RIGHT;
13725
+ const plotHeight = CHART_HEIGHT - PAD_TOP - PAD_BOTTOM;
13726
+ const xFor = useCallback39(
13727
+ (i, n) => PAD_LEFT + (n === 1 ? plotWidth / 2 : i / (n - 1) * plotWidth),
13728
+ [plotWidth]
13729
+ );
13730
+ const yFor = useCallback39(
13731
+ (score) => PAD_TOP + plotHeight - score / Y_MAX * plotHeight,
13732
+ [plotHeight]
13733
+ );
13734
+ const computed = useMemo17(
13735
+ () => points.map((p, i) => ({
13736
+ ...p,
13737
+ x: xFor(i, points.length),
13738
+ y: yFor(p.score)
13739
+ })),
13740
+ [points, xFor, yFor]
13741
+ );
13742
+ const polylinePoints = useMemo17(
13743
+ () => computed.map((p) => `${p.x},${p.y}`).join(" "),
13744
+ [computed]
13745
+ );
13746
+ const maPoints = useMemo17(() => {
13747
+ if (!showMovingAverage || movingAverage.length !== computed.length)
13748
+ return "";
13749
+ return computed.map((p, i) => `${p.x},${yFor(movingAverage[i] ?? p.score)}`).join(" ");
13750
+ }, [computed, movingAverage, showMovingAverage, yFor]);
13444
13751
  const avgScore = useMemo17(() => {
13445
- if (chartPoints.length === 0) return 0;
13446
- return chartPoints.reduce((sum, p) => sum + p.score, 0) / chartPoints.length;
13447
- }, [chartPoints]);
13448
- const handleRangeChange = useCallback38(
13752
+ if (computed.length === 0) return 0;
13753
+ return computed.reduce((acc, p) => acc + p.score, 0) / computed.length;
13754
+ }, [computed]);
13755
+ const xLabelIndexes = useMemo17(() => {
13756
+ if (computed.length === 0) return [];
13757
+ if (computed.length <= X_LABEL_TARGET) return computed.map((_, i) => i);
13758
+ const step = (computed.length - 1) / (X_LABEL_TARGET - 1);
13759
+ const out = [];
13760
+ for (let k = 0; k < X_LABEL_TARGET; k++) {
13761
+ out.push(Math.round(k * step));
13762
+ }
13763
+ return Array.from(new Set(out));
13764
+ }, [computed]);
13765
+ const findNearestIndex = useCallback39(
13766
+ (clientX, rect) => {
13767
+ if (computed.length === 0) return null;
13768
+ const localX = (clientX - rect.left) * width / rect.width;
13769
+ let best = 0;
13770
+ let bestDist = Math.abs(computed[0].x - localX);
13771
+ for (let i = 1; i < computed.length; i++) {
13772
+ const d = Math.abs(computed[i].x - localX);
13773
+ if (d < bestDist) {
13774
+ best = i;
13775
+ bestDist = d;
13776
+ }
13777
+ }
13778
+ return best;
13779
+ },
13780
+ [computed, width]
13781
+ );
13782
+ const handleMouseMove = useCallback39(
13449
13783
  (e) => {
13450
- const val = e.currentTarget.value;
13451
- setRangeDays(val === "all" ? null : Number(val));
13784
+ const rect = e.currentTarget.getBoundingClientRect();
13785
+ const idx = findNearestIndex(e.clientX, rect);
13786
+ setHoverIdx(idx);
13452
13787
  },
13453
- []
13788
+ [findNearestIndex]
13454
13789
  );
13455
- const handleAreaChange = useCallback38(
13790
+ const handleMouseLeave = useCallback39(() => {
13791
+ setHoverIdx(null);
13792
+ }, []);
13793
+ const handlePointClick = useCallback39(
13794
+ (idx) => {
13795
+ const datum = computed[idx];
13796
+ if (!datum) return;
13797
+ onSelectPoint(datum.source);
13798
+ },
13799
+ [computed, onSelectPoint]
13800
+ );
13801
+ const handleFocus = useCallback39(() => {
13802
+ setFocusIdx((prev) => prev ?? 0);
13803
+ }, []);
13804
+ const moveTo = useCallback39((idx) => {
13805
+ setFocusIdx(idx);
13806
+ setHoverIdx(idx);
13807
+ }, []);
13808
+ const handleKey = useCallback39(
13456
13809
  (e) => {
13457
- const val = e.currentTarget.value;
13458
- setSelectedArea(val || null);
13810
+ if (computed.length === 0) return;
13811
+ const last = computed.length - 1;
13812
+ const cur = focusIdx ?? 0;
13813
+ switch (e.key) {
13814
+ case "ArrowRight":
13815
+ e.preventDefault();
13816
+ moveTo(Math.min(last, cur + 1));
13817
+ return;
13818
+ case "ArrowLeft":
13819
+ e.preventDefault();
13820
+ moveTo(Math.max(0, cur - 1));
13821
+ return;
13822
+ case "Home":
13823
+ e.preventDefault();
13824
+ moveTo(0);
13825
+ return;
13826
+ case "End":
13827
+ e.preventDefault();
13828
+ moveTo(last);
13829
+ return;
13830
+ case "Enter":
13831
+ case " ":
13832
+ e.preventDefault();
13833
+ handlePointClick(cur);
13834
+ }
13459
13835
  },
13460
- []
13836
+ [computed, focusIdx, handlePointClick, moveTo]
13461
13837
  );
13462
- const polylinePoints = chartPoints.map((p) => `${p.x},${p.y}`).join(" ");
13463
- return /* @__PURE__ */ jsxs50(Stack39, { space: 4, children: [
13464
- /* @__PURE__ */ jsxs50(Flex36, { gap: 3, children: [
13465
- /* @__PURE__ */ jsx66(
13466
- Select2,
13838
+ const activeIdx = hoverIdx ?? focusIdx;
13839
+ const active = activeIdx !== null ? computed[activeIdx] : null;
13840
+ if (computed.length === 0) {
13841
+ return /* @__PURE__ */ jsx67(Card23, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsx67(Flex36, { align: "center", justify: "center", style: { height: 220 }, children: /* @__PURE__ */ jsx67(Text50, { muted: true, size: 2, children: "No reports found in this window. Adjust the filters or extend the time range." }) }) });
13842
+ }
13843
+ return /* @__PURE__ */ jsx67(Card23, { padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs50(Stack39, { space: 2, children: [
13844
+ /* @__PURE__ */ jsxs50(Box34, { ref: containerRef, style: { position: "relative", width: "100%" }, children: [
13845
+ /* @__PURE__ */ jsxs50(
13846
+ "svg",
13467
13847
  {
13468
- onChange: handleRangeChange,
13469
- value: rangeDays?.toString() ?? "all",
13470
- children: TIME_RANGES.map((r) => /* @__PURE__ */ jsx66("option", { value: r.days?.toString() ?? "all", children: r.label }, r.label))
13848
+ "aria-label": "Score timeline chart",
13849
+ onFocus: handleFocus,
13850
+ onKeyDown: handleKey,
13851
+ onMouseLeave: handleMouseLeave,
13852
+ onMouseMove: handleMouseMove,
13853
+ role: "img",
13854
+ style: { display: "block", width: "100%" },
13855
+ tabIndex: 0,
13856
+ viewBox: `0 0 ${width} ${CHART_HEIGHT}`,
13857
+ children: [
13858
+ Y_TICKS.map((tick) => {
13859
+ const y = yFor(tick);
13860
+ return /* @__PURE__ */ jsxs50("g", { children: [
13861
+ /* @__PURE__ */ jsx67(
13862
+ "line",
13863
+ {
13864
+ stroke: "var(--card-border-color, #ddd)",
13865
+ strokeDasharray: "3 4",
13866
+ x1: PAD_LEFT,
13867
+ x2: width - PAD_RIGHT,
13868
+ y1: y,
13869
+ y2: y
13870
+ }
13871
+ ),
13872
+ /* @__PURE__ */ jsx67(
13873
+ "text",
13874
+ {
13875
+ dominantBaseline: "middle",
13876
+ fill: "var(--card-muted-fg-color, #999)",
13877
+ fontSize: 11,
13878
+ textAnchor: "end",
13879
+ x: PAD_LEFT - 6,
13880
+ y,
13881
+ children: tick
13882
+ }
13883
+ )
13884
+ ] }, tick);
13885
+ }),
13886
+ avgScore > 0 ? /* @__PURE__ */ jsx67(
13887
+ "rect",
13888
+ {
13889
+ fill: scoreHex(avgScore),
13890
+ fillOpacity: 0.07,
13891
+ height: Math.max(
13892
+ 0,
13893
+ yFor(avgScore - NOISE_BAND) - yFor(avgScore + NOISE_BAND)
13894
+ ),
13895
+ width: width - PAD_LEFT - PAD_RIGHT,
13896
+ x: PAD_LEFT,
13897
+ y: yFor(avgScore + NOISE_BAND)
13898
+ }
13899
+ ) : null,
13900
+ xLabelIndexes.map((i) => {
13901
+ const p = computed[i];
13902
+ if (!p) return null;
13903
+ return /* @__PURE__ */ jsx67(
13904
+ "text",
13905
+ {
13906
+ fill: "var(--card-muted-fg-color, #999)",
13907
+ fontSize: 10,
13908
+ textAnchor: i === 0 ? "start" : i === computed.length - 1 ? "end" : "middle",
13909
+ x: p.x,
13910
+ y: CHART_HEIGHT - 10,
13911
+ children: formatDateShort(p.date)
13912
+ },
13913
+ i
13914
+ );
13915
+ }),
13916
+ showMovingAverage && maPoints ? /* @__PURE__ */ jsx67(
13917
+ "polyline",
13918
+ {
13919
+ fill: "none",
13920
+ points: maPoints,
13921
+ stroke: "var(--card-muted-fg-color, #888)",
13922
+ strokeDasharray: "6 4",
13923
+ strokeLinejoin: "round",
13924
+ strokeWidth: 1.5
13925
+ }
13926
+ ) : null,
13927
+ /* @__PURE__ */ jsx67(
13928
+ "polyline",
13929
+ {
13930
+ fill: "none",
13931
+ points: polylinePoints,
13932
+ stroke: scoreHex(avgScore),
13933
+ strokeLinejoin: "round",
13934
+ strokeWidth: 2.5
13935
+ }
13936
+ ),
13937
+ active ? /* @__PURE__ */ jsx67(
13938
+ "line",
13939
+ {
13940
+ stroke: "var(--card-border-color, #bbb)",
13941
+ strokeWidth: 1,
13942
+ x1: active.x,
13943
+ x2: active.x,
13944
+ y1: PAD_TOP,
13945
+ y2: CHART_HEIGHT - PAD_BOTTOM
13946
+ }
13947
+ ) : null,
13948
+ computed.map((p, idx) => {
13949
+ const isActive = idx === activeIdx;
13950
+ return /* @__PURE__ */ jsx67(
13951
+ "circle",
13952
+ {
13953
+ cx: p.x,
13954
+ cy: p.y,
13955
+ fill: scoreHex(p.score),
13956
+ onClick: () => handlePointClick(idx),
13957
+ r: isActive ? 6 : 4,
13958
+ stroke: "var(--card-bg-color, #fff)",
13959
+ strokeWidth: isActive ? 2 : 1.5,
13960
+ style: { cursor: "pointer" }
13961
+ },
13962
+ idx
13963
+ );
13964
+ })
13965
+ ]
13471
13966
  }
13472
13967
  ),
13473
- /* @__PURE__ */ jsxs50(Select2, { onChange: handleAreaChange, value: selectedArea ?? "", children: [
13474
- /* @__PURE__ */ jsx66("option", { value: "", children: "Overall" }),
13475
- areaNames.map((name) => /* @__PURE__ */ jsx66("option", { value: name, children: name }, name))
13476
- ] })
13968
+ active ? /* @__PURE__ */ jsx67(Tooltip13, { active, chartWidth: width }) : null
13477
13969
  ] }),
13478
- /* @__PURE__ */ jsx66(Card23, { padding: 3, radius: 2, shadow: 1, children: loading ? /* @__PURE__ */ jsx66(Flex36, { align: "center", justify: "center", style: { height: 200 }, children: /* @__PURE__ */ jsx66(Text50, { muted: true, size: 2, children: "Loading\u2026" }) }) : chartPoints.length === 0 ? /* @__PURE__ */ jsx66(Flex36, { align: "center", justify: "center", style: { height: 200 }, children: /* @__PURE__ */ jsx66(Text50, { muted: true, size: 2, children: "No reports found for this time range" }) }) : /* @__PURE__ */ jsxs50(
13479
- "svg",
13970
+ /* @__PURE__ */ jsxs50(Flex36, { gap: 3, align: "center", children: [
13971
+ /* @__PURE__ */ jsx67(LegendDot, { color: scoreHex(avgScore), label: "Score" }),
13972
+ showMovingAverage ? /* @__PURE__ */ jsx67(
13973
+ LegendDot,
13974
+ {
13975
+ color: "var(--card-muted-fg-color, #888)",
13976
+ dashed: true,
13977
+ label: "5-point moving average"
13978
+ }
13979
+ ) : null,
13980
+ /* @__PURE__ */ jsx67(Text50, { muted: true, size: 1, children: "Click a point to open the report" })
13981
+ ] })
13982
+ ] }) });
13983
+ }
13984
+ function LegendDot({
13985
+ color,
13986
+ dashed = false,
13987
+ label
13988
+ }) {
13989
+ return /* @__PURE__ */ jsxs50(Flex36, { align: "center", gap: 2, children: [
13990
+ /* @__PURE__ */ jsx67("svg", { height: "10", width: "22", children: /* @__PURE__ */ jsx67(
13991
+ "line",
13480
13992
  {
13481
- style: { display: "block", width: "100%" },
13482
- viewBox: `0 0 ${CHART_WIDTH} ${CHART_HEIGHT}`,
13483
- children: [
13484
- Y_TICKS.map((tick) => {
13485
- const y = PAD_TOP + PLOT_HEIGHT - tick / Y_MAX * PLOT_HEIGHT;
13486
- return /* @__PURE__ */ jsxs50("g", { children: [
13487
- /* @__PURE__ */ jsx66(
13488
- "line",
13489
- {
13490
- stroke: "#ccc",
13491
- strokeDasharray: "4 4",
13492
- x1: PAD_LEFT,
13493
- x2: CHART_WIDTH - PAD_RIGHT,
13494
- y1: y,
13495
- y2: y
13496
- }
13497
- ),
13498
- /* @__PURE__ */ jsx66(
13499
- "text",
13500
- {
13501
- dominantBaseline: "middle",
13502
- fill: "#999",
13503
- fontSize: 11,
13504
- textAnchor: "end",
13505
- x: PAD_LEFT - 6,
13506
- y,
13507
- children: tick
13508
- }
13509
- )
13510
- ] }, tick);
13511
- }),
13512
- chartPoints.length >= 3 ? [
13513
- 0,
13514
- Math.floor(chartPoints.length / 2),
13515
- chartPoints.length - 1
13516
- ].map((idx) => {
13517
- const p = chartPoints[idx];
13518
- return /* @__PURE__ */ jsx66(
13519
- "text",
13520
- {
13521
- fill: "#999",
13522
- fontSize: 10,
13523
- textAnchor: "middle",
13524
- x: p.x,
13525
- y: CHART_HEIGHT - 6,
13526
- children: formatDate(p.date)
13527
- },
13528
- idx
13529
- );
13530
- }) : chartPoints.map((p, idx) => /* @__PURE__ */ jsx66(
13531
- "text",
13532
- {
13533
- fill: "#999",
13534
- fontSize: 10,
13535
- textAnchor: "middle",
13536
- x: p.x,
13537
- y: CHART_HEIGHT - 6,
13538
- children: formatDate(p.date)
13539
- },
13540
- idx
13541
- )),
13542
- /* @__PURE__ */ jsx66(
13543
- "polyline",
13993
+ stroke: color,
13994
+ strokeDasharray: dashed ? "4 3" : void 0,
13995
+ strokeWidth: 2.5,
13996
+ x1: "0",
13997
+ x2: "22",
13998
+ y1: "5",
13999
+ y2: "5"
14000
+ }
14001
+ ) }),
14002
+ /* @__PURE__ */ jsx67(Text50, { muted: true, size: 1, children: label })
14003
+ ] });
14004
+ }
14005
+ function Tooltip13({ active, chartWidth }) {
14006
+ const cssX = active.x;
14007
+ const isRightEdge = cssX > chartWidth - 220;
14008
+ const left = isRightEdge ? cssX - 220 : cssX + 12;
14009
+ return /* @__PURE__ */ jsx67(
14010
+ Box34,
14011
+ {
14012
+ style: {
14013
+ background: "var(--card-bg-color, #fff)",
14014
+ border: "1px solid var(--card-border-color, #ddd)",
14015
+ borderRadius: 4,
14016
+ boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
14017
+ left,
14018
+ maxWidth: 240,
14019
+ minWidth: 180,
14020
+ padding: 8,
14021
+ pointerEvents: "none",
14022
+ position: "absolute",
14023
+ top: 8
14024
+ },
14025
+ children: /* @__PURE__ */ jsxs50(Stack39, { space: 2, children: [
14026
+ /* @__PURE__ */ jsx67(Text50, { size: 1, weight: "semibold", children: formatDateTime(active.date) }),
14027
+ /* @__PURE__ */ jsxs50(Flex36, { gap: 2, align: "center", children: [
14028
+ /* @__PURE__ */ jsx67(
14029
+ Box34,
13544
14030
  {
13545
- fill: "none",
13546
- points: polylinePoints,
13547
- stroke: scoreHex(avgScore),
13548
- strokeLinejoin: "round",
13549
- strokeWidth: 2.5
14031
+ style: {
14032
+ background: scoreHex(active.score),
14033
+ borderRadius: "50%",
14034
+ height: 10,
14035
+ width: 10
14036
+ }
13550
14037
  }
13551
14038
  ),
13552
- chartPoints.map((p, idx) => /* @__PURE__ */ jsx66(
13553
- "circle",
13554
- {
13555
- cx: p.x,
13556
- cy: p.y,
13557
- fill: scoreHex(p.score),
13558
- r: 4,
13559
- stroke: "#fff",
13560
- strokeWidth: 1.5,
13561
- children: /* @__PURE__ */ jsxs50("title", { children: [
13562
- formatDate(p.date),
13563
- ": ",
13564
- Math.round(p.score)
13565
- ] })
13566
- },
13567
- idx
13568
- ))
13569
- ]
14039
+ /* @__PURE__ */ jsx67(Text50, { size: 2, weight: "bold", children: Math.round(active.score) }),
14040
+ active.count > 1 ? /* @__PURE__ */ jsxs50(Text50, { muted: true, size: 1, children: [
14041
+ "avg of ",
14042
+ active.count,
14043
+ " reports"
14044
+ ] }) : null
14045
+ ] }),
14046
+ active.source.title ? /* @__PURE__ */ jsx67(Text50, { size: 1, children: active.source.title }) : null,
14047
+ /* @__PURE__ */ jsxs50(Text50, { muted: true, size: 1, children: [
14048
+ active.source.mode,
14049
+ active.source.source ? ` \xB7 ${active.source.source}` : ""
14050
+ ] }),
14051
+ active.source.tag ? /* @__PURE__ */ jsxs50(Text50, { muted: true, size: 1, children: [
14052
+ "tag: ",
14053
+ active.source.tag
14054
+ ] }) : null
14055
+ ] })
14056
+ }
14057
+ );
14058
+ }
14059
+
14060
+ // src/components/timeline/TimelineFilters.tsx
14061
+ import {
14062
+ ClipboardIcon as ClipboardIcon2,
14063
+ DownloadIcon as DownloadIcon2,
14064
+ LinkIcon as LinkIcon4,
14065
+ RefreshIcon
14066
+ } from "@sanity/icons";
14067
+ import { Box as Box35, Button as Button14, Inline as Inline3, MenuDivider as MenuDivider4, MenuItem as MenuItem11 } from "@sanity/ui";
14068
+ import { useCallback as useCallback40 } from "react";
14069
+
14070
+ // src/components/timeline/SelectChip.tsx
14071
+ import { ChevronDownIcon as ChevronDownIcon5 } from "@sanity/icons";
14072
+ import { Button as Button13, Menu as Menu3, MenuButton as MenuButton3, MenuItem as MenuItem10 } from "@sanity/ui";
14073
+ import { useId as useId2 } from "react";
14074
+ import { jsx as jsx68 } from "react/jsx-runtime";
14075
+ function SelectChip({
14076
+ defaultValue,
14077
+ label,
14078
+ onChange,
14079
+ options,
14080
+ value
14081
+ }) {
14082
+ const menuId = useId2();
14083
+ const current = options.find((o) => o.value === value);
14084
+ const displayValue = current?.label ?? value;
14085
+ const isActive = defaultValue !== void 0 && value !== defaultValue;
14086
+ return /* @__PURE__ */ jsx68(
14087
+ MenuButton3,
14088
+ {
14089
+ button: /* @__PURE__ */ jsx68(
14090
+ Button13,
14091
+ {
14092
+ fontSize: 1,
14093
+ iconRight: ChevronDownIcon5,
14094
+ mode: isActive ? "default" : "ghost",
14095
+ padding: 2,
14096
+ radius: 6,
14097
+ text: `${label}: ${displayValue}`,
14098
+ tone: isActive ? "primary" : "default"
14099
+ }
14100
+ ),
14101
+ id: menuId,
14102
+ menu: /* @__PURE__ */ jsx68(Menu3, { style: { minWidth: 160 }, children: options.map((opt) => /* @__PURE__ */ jsx68(
14103
+ MenuItem10,
14104
+ {
14105
+ onClick: () => onChange(opt.value),
14106
+ selected: value === opt.value,
14107
+ text: opt.label
14108
+ },
14109
+ opt.value
14110
+ )) }),
14111
+ popover: {
14112
+ animate: true,
14113
+ constrainSize: true,
14114
+ placement: "bottom-start",
14115
+ portal: true
13570
14116
  }
13571
- ) }),
13572
- /* @__PURE__ */ jsxs50(Text50, { muted: true, size: 2, children: [
13573
- chartPoints.length,
13574
- " data point",
13575
- chartPoints.length !== 1 ? "s" : ""
14117
+ }
14118
+ );
14119
+ }
14120
+
14121
+ // src/components/timeline/TimelineFilters.tsx
14122
+ import { Fragment as Fragment15, jsx as jsx69, jsxs as jsxs51 } from "react/jsx-runtime";
14123
+ var BAR_STYLE2 = {
14124
+ alignItems: "center",
14125
+ background: "var(--card-bg-color)",
14126
+ border: "1px solid var(--card-border-color, transparent)",
14127
+ borderRadius: 4,
14128
+ display: "flex",
14129
+ flexWrap: "wrap",
14130
+ gap: 8,
14131
+ padding: "8px 12px"
14132
+ };
14133
+ function TimelineFilters(props) {
14134
+ const {
14135
+ area,
14136
+ areaOptions,
14137
+ granularity,
14138
+ loading,
14139
+ mode,
14140
+ modeOptions,
14141
+ onAreaChange,
14142
+ onCopyCsv,
14143
+ onCopyUrl,
14144
+ onExportCsv,
14145
+ onGranularityChange,
14146
+ onModeChange,
14147
+ onOwnerTeamChange,
14148
+ onRangeChange,
14149
+ onRefresh,
14150
+ onShowMovingAverageChange,
14151
+ onSourceChange,
14152
+ ownerTeam,
14153
+ ownerTeamOptions,
14154
+ range,
14155
+ showMovingAverage,
14156
+ source,
14157
+ sourceOptions
14158
+ } = props;
14159
+ const handleMaToggle = useCallback40(() => {
14160
+ onShowMovingAverageChange(!showMovingAverage);
14161
+ }, [onShowMovingAverageChange, showMovingAverage]);
14162
+ return /* @__PURE__ */ jsxs51("div", { style: BAR_STYLE2, children: [
14163
+ /* @__PURE__ */ jsx69(
14164
+ SelectChip,
14165
+ {
14166
+ defaultValue: DEFAULT_RANGE,
14167
+ label: "Range",
14168
+ onChange: onRangeChange,
14169
+ options: RANGE_OPTIONS,
14170
+ value: range
14171
+ }
14172
+ ),
14173
+ /* @__PURE__ */ jsx69(
14174
+ SelectChip,
14175
+ {
14176
+ defaultValue: DEFAULT_GRANULARITY,
14177
+ label: "Aggregate",
14178
+ onChange: onGranularityChange,
14179
+ options: GRANULARITY_OPTIONS,
14180
+ value: granularity
14181
+ }
14182
+ ),
14183
+ areaOptions.length > 0 && /* @__PURE__ */ jsx69(
14184
+ FilterChip,
14185
+ {
14186
+ label: "Area",
14187
+ onChange: onAreaChange,
14188
+ options: areaOptions,
14189
+ searchable: true,
14190
+ value: area
14191
+ }
14192
+ ),
14193
+ modeOptions.length > 0 && /* @__PURE__ */ jsx69(
14194
+ FilterChip,
14195
+ {
14196
+ label: "Mode",
14197
+ onChange: onModeChange,
14198
+ options: modeOptions,
14199
+ value: mode
14200
+ }
14201
+ ),
14202
+ sourceOptions.length > 0 && /* @__PURE__ */ jsx69(
14203
+ FilterChip,
14204
+ {
14205
+ label: "Source",
14206
+ onChange: onSourceChange,
14207
+ options: sourceOptions,
14208
+ value: source
14209
+ }
14210
+ ),
14211
+ ownerTeamOptions.length > 0 && /* @__PURE__ */ jsx69(
14212
+ FilterChip,
14213
+ {
14214
+ label: "Team",
14215
+ onChange: onOwnerTeamChange,
14216
+ options: ownerTeamOptions,
14217
+ searchable: true,
14218
+ value: ownerTeam
14219
+ }
14220
+ ),
14221
+ /* @__PURE__ */ jsx69(Box35, { style: { flex: "1 0 0px" } }),
14222
+ /* @__PURE__ */ jsxs51(Inline3, { space: 1, children: [
14223
+ /* @__PURE__ */ jsx69(
14224
+ Button14,
14225
+ {
14226
+ fontSize: 1,
14227
+ mode: showMovingAverage ? "default" : "ghost",
14228
+ onClick: handleMaToggle,
14229
+ padding: 2,
14230
+ radius: 6,
14231
+ text: "5-pt MA",
14232
+ tone: showMovingAverage ? "primary" : "default"
14233
+ }
14234
+ ),
14235
+ /* @__PURE__ */ jsx69(
14236
+ Button14,
14237
+ {
14238
+ fontSize: 1,
14239
+ icon: RefreshIcon,
14240
+ mode: "ghost",
14241
+ onClick: onRefresh,
14242
+ disabled: loading,
14243
+ padding: 2,
14244
+ radius: 6,
14245
+ text: "Refresh"
14246
+ }
14247
+ ),
14248
+ /* @__PURE__ */ jsx69(
14249
+ SplitActionButton,
14250
+ {
14251
+ menuId: "timeline-share-actions",
14252
+ menu: /* @__PURE__ */ jsxs51(Fragment15, { children: [
14253
+ /* @__PURE__ */ jsx69(
14254
+ MenuItem11,
14255
+ {
14256
+ icon: ClipboardIcon2,
14257
+ onClick: onCopyCsv,
14258
+ text: "Copy CSV to clipboard"
14259
+ }
14260
+ ),
14261
+ /* @__PURE__ */ jsx69(MenuDivider4, {}),
14262
+ /* @__PURE__ */ jsx69(
14263
+ MenuItem11,
14264
+ {
14265
+ icon: DownloadIcon2,
14266
+ onClick: onExportCsv,
14267
+ text: "Export CSV"
14268
+ }
14269
+ )
14270
+ ] }),
14271
+ primary: {
14272
+ fontSize: 1,
14273
+ icon: LinkIcon4,
14274
+ onClick: onCopyUrl,
14275
+ padding: 2,
14276
+ text: "Copy URL"
14277
+ }
14278
+ }
14279
+ )
14280
+ ] })
14281
+ ] });
14282
+ }
14283
+
14284
+ // src/components/timeline/TimelineSummary.tsx
14285
+ import { Badge as Badge13, Box as Box36, Card as Card24, Flex as Flex37, Grid as Grid7, Stack as Stack40, Text as Text51 } from "@sanity/ui";
14286
+ import { jsx as jsx70, jsxs as jsxs52 } from "react/jsx-runtime";
14287
+ function TimelineSummary({ area, stats }) {
14288
+ if (stats.count === 0) return null;
14289
+ return /* @__PURE__ */ jsx70(Card24, { padding: 3, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs52(Stack40, { space: 3, children: [
14290
+ /* @__PURE__ */ jsxs52(Flex37, { align: "center", gap: 2, children: [
14291
+ /* @__PURE__ */ jsx70(Text51, { size: 1, weight: "semibold", children: "Summary" }),
14292
+ /* @__PURE__ */ jsxs52(Text51, { muted: true, size: 1, children: [
14293
+ area ? `Area: ${area}` : "Overall score",
14294
+ " \xB7 ",
14295
+ stats.count,
14296
+ " report",
14297
+ stats.count === 1 ? "" : "s"
14298
+ ] }),
14299
+ /* @__PURE__ */ jsx70(Box36, { flex: 1 }),
14300
+ /* @__PURE__ */ jsx70(TrendPill, { stats })
14301
+ ] }),
14302
+ /* @__PURE__ */ jsxs52(Grid7, { columns: [2, 2, 4], gap: 3, children: [
14303
+ /* @__PURE__ */ jsx70(
14304
+ StatTile,
14305
+ {
14306
+ label: "Mean",
14307
+ score: stats.mean,
14308
+ sub: stats.stdev !== null ? `\xB1 ${stats.stdev.toFixed(1)} stdev` : null
14309
+ }
14310
+ ),
14311
+ /* @__PURE__ */ jsx70(StatTile, { label: "Median", score: stats.median, sub: null }),
14312
+ /* @__PURE__ */ jsx70(
14313
+ StatTile,
14314
+ {
14315
+ label: "Best",
14316
+ score: stats.max?.score ?? null,
14317
+ sub: stats.max ? formatDateShort(stats.max.date) : null
14318
+ }
14319
+ ),
14320
+ /* @__PURE__ */ jsx70(
14321
+ StatTile,
14322
+ {
14323
+ label: "Worst",
14324
+ score: stats.min?.score ?? null,
14325
+ sub: stats.min ? formatDateShort(stats.min.date) : null
14326
+ }
14327
+ )
14328
+ ] })
14329
+ ] }) });
14330
+ }
14331
+ function TrendPill({ stats }) {
14332
+ if (stats.delta === null || stats.count < 2) {
14333
+ return /* @__PURE__ */ jsx70(Badge13, { fontSize: 1, mode: "outline", tone: "default", children: "Single data point" });
14334
+ }
14335
+ const { label, tone } = trendBadgeContent(stats.trend, stats.delta);
14336
+ return /* @__PURE__ */ jsx70(Badge13, { fontSize: 1, mode: "default", tone, children: label });
14337
+ }
14338
+ function trendBadgeContent(trend, delta) {
14339
+ switch (trend) {
14340
+ case "up":
14341
+ return { label: `\u2191 ${formatDelta(delta)} pts vs first`, tone: "positive" };
14342
+ case "down":
14343
+ return { label: `\u2193 ${formatDelta(delta)} pts vs first`, tone: "critical" };
14344
+ case "flat":
14345
+ return { label: "Flat (within \xB11.5)", tone: "default" };
14346
+ }
14347
+ }
14348
+ function StatTile({
14349
+ label,
14350
+ score,
14351
+ sub
14352
+ }) {
14353
+ return /* @__PURE__ */ jsxs52(Stack40, { space: 2, children: [
14354
+ /* @__PURE__ */ jsx70(Text51, { muted: true, size: 1, weight: "medium", children: label }),
14355
+ score === null ? /* @__PURE__ */ jsx70(Text51, { muted: true, size: 3, children: "\u2014" }) : /* @__PURE__ */ jsx70(Badge13, { fontSize: 2, mode: "default", tone: scoreTone(score), children: score.toFixed(1) }),
14356
+ score !== null && sub ? /* @__PURE__ */ jsx70(Text51, { muted: true, size: 1, children: sub }) : null
14357
+ ] });
14358
+ }
14359
+
14360
+ // src/components/timeline/useTimelineData.ts
14361
+ import { useCallback as useCallback41, useEffect as useEffect17, useMemo as useMemo18, useState as useState31 } from "react";
14362
+ import { useClient as useClient13 } from "sanity";
14363
+ function useTimelineData({
14364
+ mode,
14365
+ ownerTeam,
14366
+ rangeDays,
14367
+ source
14368
+ }) {
14369
+ const client = useClient13({ apiVersion: API_VERSION });
14370
+ const [dataPoints, setDataPoints] = useState31([]);
14371
+ const [loading, setLoading] = useState31(true);
14372
+ const [error, setError] = useState31(null);
14373
+ const [reloadCounter, setReloadCounter] = useState31(0);
14374
+ const refresh = useCallback41(() => {
14375
+ setReloadCounter((n) => n + 1);
14376
+ }, []);
14377
+ const effectiveStart = useMemo18(
14378
+ () => effectiveStartDate(rangeDays),
14379
+ [rangeDays]
14380
+ );
14381
+ useEffect17(() => {
14382
+ let cancelled = false;
14383
+ setLoading(true);
14384
+ setError(null);
14385
+ client.fetch(scoreTimelineQuery, {
14386
+ mode,
14387
+ ownerTeam,
14388
+ source,
14389
+ startDate: effectiveStart
14390
+ }).then((results) => {
14391
+ if (cancelled) return;
14392
+ setDataPoints(results ?? []);
14393
+ setLoading(false);
14394
+ }).catch((err) => {
14395
+ if (cancelled) return;
14396
+ setError(
14397
+ err instanceof Error ? err.message : "Failed to load timeline data"
14398
+ );
14399
+ setDataPoints([]);
14400
+ setLoading(false);
14401
+ });
14402
+ return () => {
14403
+ cancelled = true;
14404
+ };
14405
+ }, [client, effectiveStart, mode, ownerTeam, source, reloadCounter]);
14406
+ return {
14407
+ dataPoints,
14408
+ effectiveStart,
14409
+ error,
14410
+ loading,
14411
+ refresh
14412
+ };
14413
+ }
14414
+
14415
+ // src/components/ScoreTimeline.tsx
14416
+ import { Fragment as Fragment16, jsx as jsx71, jsxs as jsxs53 } from "react/jsx-runtime";
14417
+ function buildSearchParams2(filters) {
14418
+ const params = [];
14419
+ if (filters.range !== DEFAULT_RANGE) params.push(["range", filters.range]);
14420
+ if (filters.granularity !== DEFAULT_GRANULARITY) {
14421
+ params.push(["granularity", filters.granularity]);
14422
+ }
14423
+ if (filters.area) params.push(["area", filters.area]);
14424
+ if (filters.mode) params.push(["mode", filters.mode]);
14425
+ if (filters.source) params.push(["source", filters.source]);
14426
+ if (filters.ownerTeam) params.push(["ownerTeam", filters.ownerTeam]);
14427
+ if (filters.ma) params.push(["ma", "1"]);
14428
+ return params;
14429
+ }
14430
+ function ScoreTimeline({
14431
+ mode: defaultMode = null,
14432
+ source: defaultSource = null
14433
+ }) {
14434
+ const router = useRouter4();
14435
+ const routerState = router.state;
14436
+ const urlParams = routerState._searchParams;
14437
+ const [range, setRange] = useState32(() => {
14438
+ const v = readSearchParam(urlParams, "range");
14439
+ return v && isRangePreset(v) ? v : DEFAULT_RANGE;
14440
+ });
14441
+ const [granularity, setGranularity] = useState32(() => {
14442
+ const v = readSearchParam(urlParams, "granularity");
14443
+ return v && isGranularity(v) ? v : DEFAULT_GRANULARITY;
14444
+ });
14445
+ const [area, setArea] = useState32(
14446
+ () => readSearchParam(urlParams, "area")
14447
+ );
14448
+ const [mode, setMode] = useState32(
14449
+ () => readSearchParam(urlParams, "mode") ?? defaultMode
14450
+ );
14451
+ const [source, setSource] = useState32(
14452
+ () => readSearchParam(urlParams, "source") ?? defaultSource
14453
+ );
14454
+ const [ownerTeam, setOwnerTeam] = useState32(
14455
+ () => readSearchParam(urlParams, "ownerTeam")
14456
+ );
14457
+ const [showMovingAverage, setShowMovingAverage] = useState32(
14458
+ () => readSearchParam(urlParams, "ma") === "1"
14459
+ );
14460
+ useSyncSearchParams(
14461
+ () => buildSearchParams2({
14462
+ area,
14463
+ granularity,
14464
+ ma: showMovingAverage,
14465
+ mode,
14466
+ ownerTeam,
14467
+ range,
14468
+ source
14469
+ }),
14470
+ [range, granularity, area, mode, source, ownerTeam, showMovingAverage]
14471
+ );
14472
+ const rangeDays = rangePresetToDays(range);
14473
+ const { dataPoints, error, loading, refresh } = useTimelineData({
14474
+ mode,
14475
+ ownerTeam,
14476
+ rangeDays,
14477
+ source
14478
+ });
14479
+ const areaOptions = useMemo19(
14480
+ () => uniqueSorted(dataPoints, (dp) => dp.scores.map((s) => s.feature)),
14481
+ [dataPoints]
14482
+ );
14483
+ const modeOptions = useMemo19(
14484
+ () => uniqueSorted(dataPoints, (dp) => [dp.mode]),
14485
+ [dataPoints]
14486
+ );
14487
+ const sourceOptions = useMemo19(
14488
+ () => uniqueSorted(dataPoints, (dp) => [dp.source]),
14489
+ [dataPoints]
14490
+ );
14491
+ const ownerTeamOptions = useMemo19(
14492
+ () => uniqueSorted(dataPoints, (dp) => [dp.ownerTeam]),
14493
+ [dataPoints]
14494
+ );
14495
+ const chartPoints = useMemo19(
14496
+ () => aggregate(dataPoints, area, granularity),
14497
+ [area, dataPoints, granularity]
14498
+ );
14499
+ const stats = useMemo19(() => computeStats(chartPoints, 5), [chartPoints]);
14500
+ const handleSelectPoint = useCallback42(
14501
+ (point) => {
14502
+ const id = point.reportId ?? point._id;
14503
+ router.navigate({ reportId: id });
14504
+ },
14505
+ [router]
14506
+ );
14507
+ const handleCopyUrl = useCallback42(() => {
14508
+ if (typeof window === "undefined") return;
14509
+ void copyTextToClipboard(window.location.href);
14510
+ }, []);
14511
+ const handleCopyCsv = useCallback42(() => {
14512
+ void copyTextToClipboard(toCsv(dataPoints, area));
14513
+ }, [area, dataPoints]);
14514
+ const handleExportCsv = useCallback42(() => {
14515
+ const csv = toCsv(dataPoints, area);
14516
+ const ts = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").slice(0, 19);
14517
+ downloadCsv(csv, `score-timeline-${ts}.csv`);
14518
+ }, [area, dataPoints]);
14519
+ return /* @__PURE__ */ jsxs53(Stack41, { space: 4, children: [
14520
+ /* @__PURE__ */ jsx71(
14521
+ TimelineFilters,
14522
+ {
14523
+ area,
14524
+ areaOptions,
14525
+ granularity,
14526
+ loading,
14527
+ mode,
14528
+ modeOptions,
14529
+ onAreaChange: setArea,
14530
+ onCopyCsv: handleCopyCsv,
14531
+ onCopyUrl: handleCopyUrl,
14532
+ onExportCsv: handleExportCsv,
14533
+ onGranularityChange: setGranularity,
14534
+ onModeChange: setMode,
14535
+ onOwnerTeamChange: setOwnerTeam,
14536
+ onRangeChange: setRange,
14537
+ onRefresh: refresh,
14538
+ onShowMovingAverageChange: setShowMovingAverage,
14539
+ onSourceChange: setSource,
14540
+ ownerTeam,
14541
+ ownerTeamOptions,
14542
+ range,
14543
+ showMovingAverage,
14544
+ source,
14545
+ sourceOptions
14546
+ }
14547
+ ),
14548
+ error ? /* @__PURE__ */ jsx71(Card25, { padding: 4, radius: 2, tone: "critical", children: /* @__PURE__ */ jsxs53(Text52, { size: 2, children: [
14549
+ "Failed to load timeline: ",
14550
+ error
14551
+ ] }) }) : null,
14552
+ loading ? /* @__PURE__ */ jsx71(Card25, { padding: 4, radius: 2, shadow: 1, children: /* @__PURE__ */ jsxs53(Flex38, { align: "center", gap: 2, justify: "center", style: { height: 220 }, children: [
14553
+ /* @__PURE__ */ jsx71(Spinner, { muted: true }),
14554
+ /* @__PURE__ */ jsx71(Text52, { muted: true, size: 2, children: "Loading timeline\u2026" })
14555
+ ] }) }) : /* @__PURE__ */ jsxs53(Fragment16, { children: [
14556
+ /* @__PURE__ */ jsx71(
14557
+ TimelineChart,
14558
+ {
14559
+ movingAverage: stats.movingAverage,
14560
+ onSelectPoint: handleSelectPoint,
14561
+ points: chartPoints,
14562
+ showMovingAverage
14563
+ }
14564
+ ),
14565
+ /* @__PURE__ */ jsx71(TimelineSummary, { area, stats })
13576
14566
  ] })
13577
14567
  ] });
13578
14568
  }
13579
14569
  var ScoreTimeline_default = ScoreTimeline;
13580
14570
 
13581
14571
  // src/components/Dashboard.tsx
13582
- import { jsx as jsx67, jsxs as jsxs51 } from "react/jsx-runtime";
14572
+ import { jsx as jsx72, jsxs as jsxs54 } from "react/jsx-runtime";
13583
14573
  var VIEW_PARAM_MAP = {
13584
14574
  compare: "compare",
13585
14575
  timeline: "timeline"
13586
14576
  };
13587
14577
  function Dashboard() {
13588
- return /* @__PURE__ */ jsx67(HelpProvider, { children: /* @__PURE__ */ jsx67(JudgmentDrawerProvider, { children: /* @__PURE__ */ jsx67(DashboardShell, {}) }) });
14578
+ return /* @__PURE__ */ jsx72(HelpProvider, { children: /* @__PURE__ */ jsx72(JudgmentDrawerProvider, { children: /* @__PURE__ */ jsx72(DashboardShell, {}) }) });
13589
14579
  }
13590
14580
  function DashboardShell() {
13591
- const router = useRouter4();
14581
+ const router = useRouter5();
13592
14582
  const { close: closeDrawer } = useJudgmentDrawer();
13593
14583
  const routerState = router.state;
13594
14584
  const reportId = routerState.reportId ?? null;
13595
- useEffect17(() => {
14585
+ useEffect18(() => {
13596
14586
  if (!reportId) closeDrawer();
13597
14587
  }, [reportId, closeDrawer]);
13598
- const handleJudgmentDrawerClose = useCallback39(() => {
14588
+ const handleJudgmentDrawerClose = useCallback43(() => {
13599
14589
  closeDrawer();
13600
14590
  const state = { ...router.state };
13601
14591
  if (state.focus) {
@@ -13603,21 +14593,21 @@ function DashboardShell() {
13603
14593
  router.navigate(state);
13604
14594
  }
13605
14595
  }, [closeDrawer, router]);
13606
- return /* @__PURE__ */ jsxs51(Flex37, { style: { height: "100%" }, children: [
13607
- /* @__PURE__ */ jsx67(Box34, { flex: 1, overflow: "auto", children: /* @__PURE__ */ jsx67(DashboardContent, {}) }),
13608
- /* @__PURE__ */ jsx67(JudgmentDetailDrawerOutlet, { onClose: handleJudgmentDrawerClose }),
13609
- /* @__PURE__ */ jsx67(HelpDrawer, {})
14596
+ return /* @__PURE__ */ jsxs54(Flex39, { style: { height: "100%" }, children: [
14597
+ /* @__PURE__ */ jsx72(Box37, { flex: 1, overflow: "auto", children: /* @__PURE__ */ jsx72(DashboardContent, {}) }),
14598
+ /* @__PURE__ */ jsx72(JudgmentDetailDrawerOutlet, { onClose: handleJudgmentDrawerClose }),
14599
+ /* @__PURE__ */ jsx72(HelpDrawer, {})
13610
14600
  ] });
13611
14601
  }
13612
14602
  function DashboardContent() {
13613
- const router = useRouter4();
14603
+ const router = useRouter5();
13614
14604
  const { openHelp } = useHelp();
13615
14605
  const routerState = router.state;
13616
14606
  const reportId = routerState.reportId ?? null;
13617
14607
  const isDetail = reportId !== null;
13618
14608
  const activeTab = isDetail ? "latest" : VIEW_PARAM_MAP[routerState.view ?? ""] ?? "latest";
13619
14609
  const defaultTopic = deriveHelpTopic(routerState);
13620
- const navigateToTab = useCallback39(
14610
+ const navigateToTab = useCallback43(
13621
14611
  (tab) => {
13622
14612
  if (tab === "latest") {
13623
14613
  router.navigate({});
@@ -13627,13 +14617,13 @@ function DashboardContent() {
13627
14617
  },
13628
14618
  [router]
13629
14619
  );
13630
- const handleSelectReport = useCallback39(
14620
+ const handleSelectReport = useCallback43(
13631
14621
  (id) => {
13632
14622
  router.navigate({ reportId: id });
13633
14623
  },
13634
14624
  [router]
13635
14625
  );
13636
- const handleTabChange = useCallback39(
14626
+ const handleTabChange = useCallback43(
13637
14627
  (tab, subTab, focus) => {
13638
14628
  if (!routerState.reportId) return;
13639
14629
  const state = {
@@ -13646,20 +14636,20 @@ function DashboardContent() {
13646
14636
  },
13647
14637
  [router, routerState.reportId]
13648
14638
  );
13649
- const handleBack = useCallback39(() => {
14639
+ const handleBack = useCallback43(() => {
13650
14640
  router.navigate({});
13651
14641
  }, [router]);
13652
- const handleOpenHelp = useCallback39(() => {
14642
+ const handleOpenHelp = useCallback43(() => {
13653
14643
  openHelp(defaultTopic);
13654
14644
  }, [openHelp, defaultTopic]);
13655
- return /* @__PURE__ */ jsx67(Container, { width: 4, children: /* @__PURE__ */ jsxs51(Stack40, { padding: 4, space: 4, children: [
13656
- /* @__PURE__ */ jsxs51(Flex37, { align: "center", gap: 3, children: [
13657
- /* @__PURE__ */ jsxs51(Stack40, { flex: 1, space: 1, children: [
13658
- /* @__PURE__ */ jsx67(Text51, { size: 4, weight: "bold", children: "AI Literacy Framework" }),
13659
- /* @__PURE__ */ jsx67(Text51, { muted: true, size: 2, children: "Evaluation reports and score trends" })
14645
+ return /* @__PURE__ */ jsx72(Container, { width: 4, children: /* @__PURE__ */ jsxs54(Stack42, { padding: 4, space: 4, children: [
14646
+ /* @__PURE__ */ jsxs54(Flex39, { align: "center", gap: 3, children: [
14647
+ /* @__PURE__ */ jsxs54(Stack42, { flex: 1, space: 1, children: [
14648
+ /* @__PURE__ */ jsx72(Text53, { size: 4, weight: "bold", children: "AI Literacy Framework" }),
14649
+ /* @__PURE__ */ jsx72(Text53, { muted: true, size: 2, children: "Evaluation reports and score trends" })
13660
14650
  ] }),
13661
- /* @__PURE__ */ jsx67(
13662
- Button13,
14651
+ /* @__PURE__ */ jsx72(
14652
+ Button15,
13663
14653
  {
13664
14654
  icon: HelpCircleIcon8,
13665
14655
  mode: "bleed",
@@ -13669,8 +14659,8 @@ function DashboardContent() {
13669
14659
  }
13670
14660
  )
13671
14661
  ] }),
13672
- !isDetail && /* @__PURE__ */ jsxs51(TabList3, { space: 1, children: [
13673
- /* @__PURE__ */ jsx67(
14662
+ !isDetail && /* @__PURE__ */ jsxs54(TabList3, { space: 1, children: [
14663
+ /* @__PURE__ */ jsx72(
13674
14664
  Tab3,
13675
14665
  {
13676
14666
  "aria-controls": "latest-panel",
@@ -13680,7 +14670,7 @@ function DashboardContent() {
13680
14670
  selected: activeTab === "latest"
13681
14671
  }
13682
14672
  ),
13683
- /* @__PURE__ */ jsx67(
14673
+ /* @__PURE__ */ jsx72(
13684
14674
  Tab3,
13685
14675
  {
13686
14676
  "aria-controls": "timeline-panel",
@@ -13690,7 +14680,7 @@ function DashboardContent() {
13690
14680
  selected: activeTab === "timeline"
13691
14681
  }
13692
14682
  ),
13693
- /* @__PURE__ */ jsx67(
14683
+ /* @__PURE__ */ jsx72(
13694
14684
  Tab3,
13695
14685
  {
13696
14686
  "aria-controls": "compare-panel",
@@ -13701,10 +14691,10 @@ function DashboardContent() {
13701
14691
  }
13702
14692
  )
13703
14693
  ] }),
13704
- !isDetail && activeTab === "latest" && /* @__PURE__ */ jsx67(TabPanel3, { "aria-labelledby": "latest-tab", id: "latest-panel", children: /* @__PURE__ */ jsx67(LatestReports, { onSelectReport: handleSelectReport }) }),
13705
- !isDetail && activeTab === "timeline" && /* @__PURE__ */ jsx67(TabPanel3, { "aria-labelledby": "timeline-tab", id: "timeline-panel", children: /* @__PURE__ */ jsx67(ScoreTimeline_default, {}) }),
13706
- !isDetail && activeTab === "compare" && /* @__PURE__ */ jsx67(TabPanel3, { "aria-labelledby": "compare-tab", id: "compare-panel", children: /* @__PURE__ */ jsx67(ComparisonView, {}) }),
13707
- isDetail && reportId && /* @__PURE__ */ jsx67(
14694
+ !isDetail && activeTab === "latest" && /* @__PURE__ */ jsx72(TabPanel3, { "aria-labelledby": "latest-tab", id: "latest-panel", children: /* @__PURE__ */ jsx72(LatestReports, { onSelectReport: handleSelectReport }) }),
14695
+ !isDetail && activeTab === "timeline" && /* @__PURE__ */ jsx72(TabPanel3, { "aria-labelledby": "timeline-tab", id: "timeline-panel", children: /* @__PURE__ */ jsx72(ScoreTimeline_default, {}) }),
14696
+ !isDetail && activeTab === "compare" && /* @__PURE__ */ jsx72(TabPanel3, { "aria-labelledby": "compare-tab", id: "compare-panel", children: /* @__PURE__ */ jsx72(ComparisonView, {}) }),
14697
+ isDetail && reportId && /* @__PURE__ */ jsx72(
13708
14698
  ReportDetail,
13709
14699
  {
13710
14700
  activeTab: routerState.tab ?? null,
@@ -13772,7 +14762,7 @@ var ailfStructure = (S) => S.list().id("root").title("Content").items([
13772
14762
  // src/actions/RunEvaluationAction.tsx
13773
14763
  import { BarChartIcon as BarChartIcon2 } from "@sanity/icons";
13774
14764
  import { useToast as useToast10 } from "@sanity/ui";
13775
- import { useCallback as useCallback40, useEffect as useEffect18, useRef as useRef9, useState as useState31 } from "react";
14765
+ import { useCallback as useCallback44, useEffect as useEffect19, useRef as useRef10, useState as useState33 } from "react";
13776
14766
  import {
13777
14767
  getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId3,
13778
14768
  useClient as useClient14,
@@ -13803,10 +14793,10 @@ function createRunEvaluationAction(options = {}) {
13803
14793
  const projectId = useProjectId2();
13804
14794
  const currentUser = useCurrentUser4();
13805
14795
  const toast = useToast10();
13806
- const [state, setState] = useState31({ status: "loading" });
13807
- const requestedAtRef = useRef9(null);
14796
+ const [state, setState] = useState33({ status: "loading" });
14797
+ const requestedAtRef = useRef10(null);
13808
14798
  const perspectiveId = getReleaseIdFromReleaseDocumentId3(release._id);
13809
- useEffect18(() => {
14799
+ useEffect19(() => {
13810
14800
  let cancelled = false;
13811
14801
  client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
13812
14802
  if (cancelled) return;
@@ -13829,7 +14819,7 @@ function createRunEvaluationAction(options = {}) {
13829
14819
  cancelled = true;
13830
14820
  };
13831
14821
  }, [client, perspectiveId]);
13832
- useEffect18(() => {
14822
+ useEffect19(() => {
13833
14823
  if (state.status !== "requested" && state.status !== "polling") return;
13834
14824
  const { requestId, startedAt } = state;
13835
14825
  if (state.status === "requested") {
@@ -13879,7 +14869,7 @@ function createRunEvaluationAction(options = {}) {
13879
14869
  }, POLL_INTERVAL_MS2);
13880
14870
  return () => clearInterval(interval);
13881
14871
  }, [client, perspectiveId, state]);
13882
- useEffect18(() => {
14872
+ useEffect19(() => {
13883
14873
  if (state.status !== "error") return;
13884
14874
  const timer = setTimeout(() => {
13885
14875
  client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
@@ -13899,7 +14889,7 @@ function createRunEvaluationAction(options = {}) {
13899
14889
  }, 15e3);
13900
14890
  return () => clearTimeout(timer);
13901
14891
  }, [client, perspectiveId, state]);
13902
- const handleRequest = useCallback40(async () => {
14892
+ const handleRequest = useCallback44(async () => {
13903
14893
  const releaseTitle = release.metadata?.title ?? perspectiveId ?? "release";
13904
14894
  const tag = `release-${slugify3(releaseTitle)}-${dateStamp3()}`;
13905
14895
  const now = Date.now();