@sanity/ailf-studio 0.1.10 → 0.1.11

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.
package/dist/index.js CHANGED
@@ -68,6 +68,314 @@ var GraduateToNativeAction = (props) => {
68
68
  };
69
69
  GraduateToNativeAction.displayName = "GraduateToNativeAction";
70
70
 
71
+ // src/actions/RunTaskEvaluationAction.tsx
72
+ import { PlayIcon } from "@sanity/icons";
73
+ import { useToast } from "@sanity/ui";
74
+ import { useCallback as useCallback2, useEffect, useRef, useState as useState2 } from "react";
75
+ import {
76
+ useClient as useClient2,
77
+ useCurrentUser,
78
+ useDataset,
79
+ useProjectId
80
+ } from "sanity";
81
+
82
+ // ../shared/dist/score-grades.js
83
+ var GRADE_BOUNDARIES = {
84
+ good: 80,
85
+ warning: 70,
86
+ critical: 50
87
+ };
88
+ function scoreGrade(score) {
89
+ if (score >= GRADE_BOUNDARIES.good)
90
+ return "good";
91
+ if (score >= GRADE_BOUNDARIES.warning)
92
+ return "warning";
93
+ if (score >= GRADE_BOUNDARIES.critical)
94
+ return "needs-work";
95
+ return "critical";
96
+ }
97
+
98
+ // ../shared/dist/noise-threshold.js
99
+ var NOISE_THRESHOLD = 2;
100
+
101
+ // ../shared/dist/dimension-names.js
102
+ var DIMENSION_LABELS_KEBAB = {
103
+ "code-correctness": "Code Correctness",
104
+ "doc-coverage": "Doc Coverage",
105
+ "task-completion": "Task Completion"
106
+ };
107
+
108
+ // src/types.ts
109
+ function formatPercent(n) {
110
+ if (n == null) return "\u2014";
111
+ return `${(n * 100).toFixed(0)}%`;
112
+ }
113
+ function formatRelativeTime(iso) {
114
+ const diff = Date.now() - new Date(iso).getTime();
115
+ const minutes = Math.floor(diff / 6e4);
116
+ if (minutes < 1) return "just now";
117
+ if (minutes === 1) return "1 minute ago";
118
+ if (minutes < 60) return `${minutes} minutes ago`;
119
+ const hours = Math.floor(minutes / 60);
120
+ if (hours === 1) return "1 hour ago";
121
+ if (hours < 24) return `${hours} hours ago`;
122
+ const days = Math.floor(hours / 24);
123
+ if (days === 1) return "yesterday";
124
+ if (days < 7) return `${days} days ago`;
125
+ const weeks = Math.floor(days / 7);
126
+ if (weeks === 1) return "1 week ago";
127
+ if (weeks < 5) return `${weeks} weeks ago`;
128
+ const months = Math.floor(days / 30);
129
+ if (months === 1) return "1 month ago";
130
+ if (months < 12) return `${months} months ago`;
131
+ const years = Math.floor(days / 365);
132
+ if (years === 1) return "1 year ago";
133
+ return `${years} years ago`;
134
+ }
135
+ function formatDelta(n) {
136
+ if (n > 0) return `+${n.toFixed(1)}`;
137
+ if (n < 0) return n.toFixed(1);
138
+ return "0";
139
+ }
140
+ function formatDuration(ms) {
141
+ if (ms < 1e3) return `${ms}ms`;
142
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
143
+ const min = Math.floor(ms / 6e4);
144
+ const sec = Math.round(ms % 6e4 / 1e3);
145
+ return `${min}m ${sec}s`;
146
+ }
147
+
148
+ // src/actions/RunTaskEvaluationAction.tsx
149
+ var EVAL_REQUEST_TYPE = "ailf.evalRequest";
150
+ var POLL_INTERVAL_MS = 15e3;
151
+ var MAX_POLL_MS = 30 * 60 * 1e3;
152
+ var EVAL_REQUEST_STATUS_QUERY = (
153
+ /* groq */
154
+ `
155
+ *[_type == "${EVAL_REQUEST_TYPE}" && _id == $id][0] {
156
+ status,
157
+ error,
158
+ reportId
159
+ }
160
+ `
161
+ );
162
+ var TASK_REPORT_QUERY = (
163
+ /* groq */
164
+ `
165
+ *[_type == "ailf.report"
166
+ && $taskId in provenance.taskIds
167
+ ] | order(completedAt desc) [0] {
168
+ reportId,
169
+ completedAt,
170
+ "overall": summary.overall.avgScore,
171
+ "taskScore": summary.scores[feature == $area][0].totalScore
172
+ }
173
+ `
174
+ );
175
+ function slugify(s) {
176
+ return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
177
+ }
178
+ function dateStamp() {
179
+ const d = /* @__PURE__ */ new Date();
180
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
181
+ }
182
+ var RunTaskEvaluationAction = (props) => {
183
+ const { type, draft, published } = props;
184
+ const client = useClient2({ apiVersion: API_VERSION });
185
+ const dataset = useDataset();
186
+ const projectId = useProjectId();
187
+ const currentUser = useCurrentUser();
188
+ const toast = useToast();
189
+ const [state, setState] = useState2({ status: "idle" });
190
+ const requestedAtRef = useRef(null);
191
+ const doc = draft ?? published;
192
+ const taskIdSlug = doc?.id;
193
+ const taskId = taskIdSlug?.current;
194
+ const featureAreaRef = doc?.featureArea;
195
+ const taskDescription = doc?.description ?? taskId ?? "this task";
196
+ const [areaId, setAreaId] = useState2(null);
197
+ useEffect(() => {
198
+ if (!featureAreaRef?._ref) return;
199
+ let cancelled = false;
200
+ client.fetch(`*[_id == $id][0].areaId`, {
201
+ id: featureAreaRef._ref
202
+ }).then((result) => {
203
+ if (!cancelled && result?.current) {
204
+ setAreaId(result.current);
205
+ }
206
+ }).catch(() => {
207
+ });
208
+ return () => {
209
+ cancelled = true;
210
+ };
211
+ }, [client, featureAreaRef?._ref]);
212
+ useEffect(() => {
213
+ if (!taskId || !areaId) return;
214
+ let cancelled = false;
215
+ client.fetch(TASK_REPORT_QUERY, {
216
+ taskId,
217
+ area: areaId
218
+ }).then((result) => {
219
+ if (cancelled || !result) return;
220
+ const score = result.taskScore ?? Math.round(result.overall);
221
+ setState({
222
+ completedAt: result.completedAt,
223
+ reportId: result.reportId,
224
+ score: Math.round(score),
225
+ status: "ready"
226
+ });
227
+ }).catch(() => {
228
+ });
229
+ return () => {
230
+ cancelled = true;
231
+ };
232
+ }, [client, taskId, areaId]);
233
+ useEffect(() => {
234
+ if (state.status !== "requested" && state.status !== "polling") return;
235
+ const { requestId, startedAt } = state;
236
+ if (state.status === "requested") {
237
+ setState({ requestId, startedAt, status: "polling" });
238
+ }
239
+ const interval = setInterval(async () => {
240
+ if (Date.now() - startedAt > MAX_POLL_MS) {
241
+ clearInterval(interval);
242
+ setState({
243
+ message: "Evaluation is still running. Check the AI Literacy dashboard for results.",
244
+ status: "error"
245
+ });
246
+ return;
247
+ }
248
+ try {
249
+ const reqStatus = await client.fetch(EVAL_REQUEST_STATUS_QUERY, {
250
+ id: requestId
251
+ });
252
+ if (reqStatus?.status === "failed") {
253
+ clearInterval(interval);
254
+ setState({
255
+ message: reqStatus.error ?? "Evaluation dispatch failed.",
256
+ status: "error"
257
+ });
258
+ return;
259
+ }
260
+ if (!taskId) return;
261
+ const result = await client.fetch(TASK_REPORT_QUERY, {
262
+ taskId,
263
+ area: areaId ?? ""
264
+ });
265
+ if (result) {
266
+ const reportTime = new Date(result.completedAt).getTime();
267
+ if (reportTime > startedAt) {
268
+ clearInterval(interval);
269
+ const score = result.taskScore ?? Math.round(result.overall);
270
+ setState({
271
+ completedAt: result.completedAt,
272
+ reportId: result.reportId,
273
+ score: Math.round(score),
274
+ status: "ready"
275
+ });
276
+ }
277
+ }
278
+ } catch {
279
+ }
280
+ }, POLL_INTERVAL_MS);
281
+ return () => clearInterval(interval);
282
+ }, [client, taskId, areaId, state]);
283
+ useEffect(() => {
284
+ if (state.status !== "error") return;
285
+ const timer = setTimeout(() => {
286
+ setState({ status: "idle" });
287
+ }, 15e3);
288
+ return () => clearTimeout(timer);
289
+ }, [state]);
290
+ const handleRequest = useCallback2(async () => {
291
+ if (!taskId) return;
292
+ const tag = `task-${slugify(taskId)}-${dateStamp()}`;
293
+ const now = Date.now();
294
+ try {
295
+ const evalRequest = await client.create({
296
+ _type: EVAL_REQUEST_TYPE,
297
+ dataset,
298
+ mode: "full",
299
+ projectId,
300
+ requestedAt: new Date(now).toISOString(),
301
+ requestedBy: currentUser?.id ?? "unknown",
302
+ status: "pending",
303
+ tag,
304
+ tasks: [taskId],
305
+ ...areaId ? { areas: [areaId] } : {}
306
+ });
307
+ requestedAtRef.current = now;
308
+ setState({
309
+ requestId: evalRequest._id,
310
+ startedAt: now,
311
+ status: "requested"
312
+ });
313
+ toast.push({
314
+ closable: true,
315
+ description: `Evaluating "${taskDescription}". Results will appear here when the pipeline completes.`,
316
+ status: "info",
317
+ title: "Task evaluation started"
318
+ });
319
+ } catch (err) {
320
+ const message = err instanceof Error ? err.message : "Failed to create evaluation request";
321
+ setState({ message, status: "error" });
322
+ toast.push({
323
+ closable: true,
324
+ description: message,
325
+ status: "error",
326
+ title: "Task evaluation failed"
327
+ });
328
+ }
329
+ }, [
330
+ client,
331
+ currentUser?.id,
332
+ dataset,
333
+ projectId,
334
+ taskId,
335
+ taskDescription,
336
+ areaId
337
+ ]);
338
+ if (type !== "ailf.task" || !taskId) return null;
339
+ return {
340
+ disabled: state.status === "requested" || state.status === "polling",
341
+ icon: PlayIcon,
342
+ label: getLabel(state),
343
+ onHandle: handleRequest,
344
+ title: getTitle(state, taskId)
345
+ };
346
+ };
347
+ RunTaskEvaluationAction.displayName = "RunTaskEvaluationAction";
348
+ function getLabel(state) {
349
+ switch (state.status) {
350
+ case "idle":
351
+ return "Run Task Eval";
352
+ case "requested":
353
+ return "Requesting\u2026";
354
+ case "polling":
355
+ return "Evaluating\u2026";
356
+ case "ready":
357
+ return `Score: ${state.score}`;
358
+ case "error":
359
+ return "Eval Failed";
360
+ }
361
+ }
362
+ function getTitle(state, taskId) {
363
+ switch (state.status) {
364
+ case "idle":
365
+ return `Run an AI Literacy evaluation for this task (${taskId}). Runs all test cases against the current documentation.`;
366
+ case "requested":
367
+ return "Creating evaluation request\u2026";
368
+ case "polling":
369
+ return "Evaluation is running. The score will appear here when complete. You can navigate away \u2014 the result will show next time you open this task.";
370
+ case "ready": {
371
+ const when = formatRelativeTime(state.completedAt);
372
+ return `Task Score: ${state.score}/100 (evaluated ${when}). Click to re-run.`;
373
+ }
374
+ case "error":
375
+ return `${state.message} Click to try again.`;
376
+ }
377
+ }
378
+
71
379
  // src/schema/eval-request.ts
72
380
  import { ALL_FIELDS_GROUP, defineField, defineType } from "sanity";
73
381
  var evalRequestSchema = defineType({
@@ -128,13 +436,38 @@ var evalRequestSchema = defineType({
128
436
  type: "string"
129
437
  }),
130
438
  defineField({
131
- description: "Content release perspective ID",
439
+ description: "Content release perspective ID (required for release evals)",
132
440
  group: ["main", "all-fields"],
133
441
  name: "perspective",
134
442
  readOnly: true,
135
443
  title: "Perspective",
136
- type: "string",
137
- validation: (rule) => rule.required()
444
+ type: "string"
445
+ }),
446
+ defineField({
447
+ description: "Specific task IDs to evaluate (for task-scoped evals). When set, the pipeline only runs these tasks instead of the full suite.",
448
+ group: ["optional", "all-fields"],
449
+ name: "tasks",
450
+ of: [{ type: "string" }],
451
+ readOnly: true,
452
+ title: "Tasks",
453
+ type: "array"
454
+ }),
455
+ defineField({
456
+ description: "Feature areas to scope the evaluation. When set together with tasks, provides additional context for the pipeline.",
457
+ group: ["optional", "all-fields"],
458
+ name: "areas",
459
+ of: [{ type: "string" }],
460
+ readOnly: true,
461
+ title: "Areas",
462
+ type: "array"
463
+ }),
464
+ defineField({
465
+ description: "Run in debug mode (limits to a subset of test cases for fast feedback).",
466
+ group: ["optional", "all-fields"],
467
+ name: "debug",
468
+ readOnly: true,
469
+ title: "Debug",
470
+ type: "boolean"
138
471
  }),
139
472
  defineField({
140
473
  description: "Sanity project ID",
@@ -199,15 +532,22 @@ var evalRequestSchema = defineType({
199
532
  ],
200
533
  name: "ailf.evalRequest",
201
534
  preview: {
202
- prepare({ perspective, status }) {
203
- return {
204
- subtitle: typeof status === "string" ? status : "unknown",
205
- title: typeof perspective === "string" ? perspective : "Evaluation Request"
206
- };
535
+ prepare({ perspective, status, tasks }) {
536
+ const statusStr = typeof status === "string" ? status : "unknown";
537
+ let title;
538
+ if (typeof perspective === "string") {
539
+ title = perspective;
540
+ } else if (Array.isArray(tasks) && tasks.length > 0) {
541
+ title = tasks.length === 1 ? `Task: ${tasks[0]}` : `Tasks: ${tasks.slice(0, 3).join(", ")}${tasks.length > 3 ? "\u2026" : ""}`;
542
+ } else {
543
+ title = "Evaluation Request";
544
+ }
545
+ return { subtitle: statusStr, title };
207
546
  },
208
547
  select: {
209
548
  perspective: "perspective",
210
- status: "status"
549
+ status: "status",
550
+ tasks: "tasks"
211
551
  }
212
552
  },
213
553
  title: "AILF Evaluation Request",
@@ -1218,7 +1558,7 @@ import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP5, defineField as defineField5, def
1218
1558
  // src/components/AssertionInput.tsx
1219
1559
  import { HelpCircleIcon } from "@sanity/icons";
1220
1560
  import { Box as Box2, Card, Flex, Stack as Stack2, Text as Text2 } from "@sanity/ui";
1221
- import { useCallback as useCallback2 } from "react";
1561
+ import { useCallback as useCallback3 } from "react";
1222
1562
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1223
1563
  var TYPE_HELP = {
1224
1564
  "llm-rubric": {
@@ -1372,7 +1712,7 @@ function AssertionInput(props) {
1372
1712
  const templateHelp = selectedTemplate ? TEMPLATE_HELP[selectedTemplate] : null;
1373
1713
  const isMonospace = selectedType ? MONOSPACE_TYPES.has(selectedType) : false;
1374
1714
  const { renderField: parentRenderField } = props;
1375
- const renderField = useCallback2(
1715
+ const renderField = useCallback3(
1376
1716
  (fieldProps) => {
1377
1717
  const rendered = parentRenderField(fieldProps);
1378
1718
  if (fieldProps.name === "type" && typeHelp) {
@@ -1400,7 +1740,7 @@ function AssertionInput(props) {
1400
1740
  // src/components/CanonicalDocInput.tsx
1401
1741
  import { HelpCircleIcon as HelpCircleIcon2 } from "@sanity/icons";
1402
1742
  import { Box as Box3, Card as Card2, Flex as Flex2, Stack as Stack3, Text as Text3 } from "@sanity/ui";
1403
- import { useCallback as useCallback3 } from "react";
1743
+ import { useCallback as useCallback4 } from "react";
1404
1744
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1405
1745
  var REF_TYPE_HELP = {
1406
1746
  slug: {
@@ -1423,7 +1763,7 @@ function CanonicalDocInput(props) {
1423
1763
  const selectedType = typeof value?.refType === "string" ? value.refType : null;
1424
1764
  const help = selectedType ? REF_TYPE_HELP[selectedType] : null;
1425
1765
  const { renderField: parentRenderField } = props;
1426
- const renderField = useCallback3(
1766
+ const renderField = useCallback4(
1427
1767
  (fieldProps) => {
1428
1768
  const rendered = parentRenderField(fieldProps);
1429
1769
  if (fieldProps.name === "refType" && help) {
@@ -1616,7 +1956,7 @@ function OriginInput(props) {
1616
1956
  // src/components/ReleasePicker.tsx
1617
1957
  import { SearchIcon } from "@sanity/icons";
1618
1958
  import { Autocomplete, Badge as Badge2, Card as Card4, Flex as Flex5, Stack as Stack6, Text as Text7 } from "@sanity/ui";
1619
- import { useCallback as useCallback4, useEffect, useMemo as useMemo2, useRef } from "react";
1959
+ import { useCallback as useCallback5, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
1620
1960
  import {
1621
1961
  getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId2,
1622
1962
  PatchEvent,
@@ -1662,8 +2002,8 @@ function ReleasePicker(props) {
1662
2002
  });
1663
2003
  return result;
1664
2004
  }, [activeReleases, archivedReleases]);
1665
- const hasSynced = useRef(false);
1666
- useEffect(() => {
2005
+ const hasSynced = useRef2(false);
2006
+ useEffect2(() => {
1667
2007
  if (hasSynced.current || !value || options.length === 0) return;
1668
2008
  const match = options.find((o) => o.value === value);
1669
2009
  if (match && match.payload.title !== value) {
@@ -1671,7 +2011,7 @@ function ReleasePicker(props) {
1671
2011
  formOnChange(PatchEvent.from(set(match.payload.title, titlePath)));
1672
2012
  }
1673
2013
  }, [value, options, formOnChange, titlePath]);
1674
- const handleChange = useCallback4(
2014
+ const handleChange = useCallback5(
1675
2015
  (newValue) => {
1676
2016
  if (newValue) {
1677
2017
  onChange(set(newValue));
@@ -2448,8 +2788,8 @@ import {
2448
2788
  TabPanel as TabPanel2,
2449
2789
  Text as Text34
2450
2790
  } from "@sanity/ui";
2451
- import { useCallback as useCallback14, useEffect as useEffect9, useState as useState11 } from "react";
2452
- import { useClient as useClient8 } from "sanity";
2791
+ import { useCallback as useCallback15, useEffect as useEffect10, useState as useState12 } from "react";
2792
+ import { useClient as useClient9 } from "sanity";
2453
2793
  import { useRouter } from "sanity/router";
2454
2794
 
2455
2795
  // src/queries.ts
@@ -2694,8 +3034,8 @@ function filterSourceClause(param) {
2694
3034
 
2695
3035
  // src/components/ComparisonView.tsx
2696
3036
  import { Badge as Badge3, Box as Box7, Card as Card6, Flex as Flex7, Grid, Select, Stack as Stack8, Text as Text11 } from "@sanity/ui";
2697
- import { useCallback as useCallback5, useEffect as useEffect2, useMemo as useMemo3, useState as useState2 } from "react";
2698
- import { useClient as useClient2 } from "sanity";
3037
+ import { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
3038
+ import { useClient as useClient3 } from "sanity";
2699
3039
 
2700
3040
  // src/glossary.ts
2701
3041
  var GLOSSARY = {
@@ -2753,32 +3093,6 @@ var GLOSSARY = {
2753
3093
  dimDocCoverage: "Change in doc coverage between runs. Positive means the docs are providing more useful information."
2754
3094
  };
2755
3095
 
2756
- // ../shared/dist/score-grades.js
2757
- var GRADE_BOUNDARIES = {
2758
- good: 80,
2759
- warning: 70,
2760
- critical: 50
2761
- };
2762
- function scoreGrade(score) {
2763
- if (score >= GRADE_BOUNDARIES.good)
2764
- return "good";
2765
- if (score >= GRADE_BOUNDARIES.warning)
2766
- return "warning";
2767
- if (score >= GRADE_BOUNDARIES.critical)
2768
- return "needs-work";
2769
- return "critical";
2770
- }
2771
-
2772
- // ../shared/dist/noise-threshold.js
2773
- var NOISE_THRESHOLD = 2;
2774
-
2775
- // ../shared/dist/dimension-names.js
2776
- var DIMENSION_LABELS_KEBAB = {
2777
- "code-correctness": "Code Correctness",
2778
- "doc-coverage": "Doc Coverage",
2779
- "task-completion": "Task Completion"
2780
- };
2781
-
2782
3096
  // src/lib/comparison.ts
2783
3097
  function scoreMap(summary) {
2784
3098
  return new Map(summary.scores.map((s) => [s.feature, s]));
@@ -2857,46 +3171,6 @@ function computeDimensionDeltas(baseline, experiment) {
2857
3171
  });
2858
3172
  }
2859
3173
 
2860
- // src/types.ts
2861
- function formatPercent(n) {
2862
- if (n == null) return "\u2014";
2863
- return `${(n * 100).toFixed(0)}%`;
2864
- }
2865
- function formatRelativeTime(iso) {
2866
- const diff = Date.now() - new Date(iso).getTime();
2867
- const minutes = Math.floor(diff / 6e4);
2868
- if (minutes < 1) return "just now";
2869
- if (minutes === 1) return "1 minute ago";
2870
- if (minutes < 60) return `${minutes} minutes ago`;
2871
- const hours = Math.floor(minutes / 60);
2872
- if (hours === 1) return "1 hour ago";
2873
- if (hours < 24) return `${hours} hours ago`;
2874
- const days = Math.floor(hours / 24);
2875
- if (days === 1) return "yesterday";
2876
- if (days < 7) return `${days} days ago`;
2877
- const weeks = Math.floor(days / 7);
2878
- if (weeks === 1) return "1 week ago";
2879
- if (weeks < 5) return `${weeks} weeks ago`;
2880
- const months = Math.floor(days / 30);
2881
- if (months === 1) return "1 month ago";
2882
- if (months < 12) return `${months} months ago`;
2883
- const years = Math.floor(days / 365);
2884
- if (years === 1) return "1 year ago";
2885
- return `${years} years ago`;
2886
- }
2887
- function formatDelta(n) {
2888
- if (n > 0) return `+${n.toFixed(1)}`;
2889
- if (n < 0) return n.toFixed(1);
2890
- return "0";
2891
- }
2892
- function formatDuration(ms) {
2893
- if (ms < 1e3) return `${ms}ms`;
2894
- if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
2895
- const min = Math.floor(ms / 6e4);
2896
- const sec = Math.round(ms % 6e4 / 1e3);
2897
- return `${min}m ${sec}s`;
2898
- }
2899
-
2900
3174
  // src/components/PageBlurb.tsx
2901
3175
  import { Card as Card5, Stack as Stack7, Text as Text8 } from "@sanity/ui";
2902
3176
  import { jsx as jsx9 } from "react/jsx-runtime";
@@ -2949,23 +3223,23 @@ function LoadingState({ message = "Loading\u2026" }) {
2949
3223
  // src/components/ComparisonView.tsx
2950
3224
  import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2951
3225
  function ComparisonView() {
2952
- const client = useClient2({ apiVersion: API_VERSION });
2953
- const [baselineId, setBaselineId] = useState2(null);
2954
- const [baselineSummary, setBaselineSummary] = useState2(
3226
+ const client = useClient3({ apiVersion: API_VERSION });
3227
+ const [baselineId, setBaselineId] = useState3(null);
3228
+ const [baselineSummary, setBaselineSummary] = useState3(
2955
3229
  null
2956
3230
  );
2957
- const [experimentId, setExperimentId] = useState2(null);
2958
- const [experimentSummary, setExperimentSummary] = useState2(null);
2959
- const [loading, setLoading] = useState2(false);
2960
- const [reports, setReports] = useState2([]);
2961
- useEffect2(() => {
3231
+ const [experimentId, setExperimentId] = useState3(null);
3232
+ const [experimentSummary, setExperimentSummary] = useState3(null);
3233
+ const [loading, setLoading] = useState3(false);
3234
+ const [reports, setReports] = useState3([]);
3235
+ useEffect3(() => {
2962
3236
  client.fetch(latestReportsQuery, {
2963
3237
  limit: 50,
2964
3238
  mode: null,
2965
3239
  source: null
2966
3240
  }).then((data) => setReports(data ?? [])).catch(() => setReports([]));
2967
3241
  }, [client]);
2968
- useEffect2(() => {
3242
+ useEffect3(() => {
2969
3243
  if (!baselineId || !experimentId) {
2970
3244
  setBaselineSummary(null);
2971
3245
  setExperimentSummary(null);
@@ -3015,11 +3289,11 @@ function ComparisonView() {
3015
3289
  const e = experimentSummary.overall.avgScore;
3016
3290
  return { baseline: b, delta: e - b, experiment: e };
3017
3291
  }, [baselineSummary, experimentSummary]);
3018
- const onBaseline = useCallback5(
3292
+ const onBaseline = useCallback6(
3019
3293
  (e) => setBaselineId(e.currentTarget.value || null),
3020
3294
  []
3021
3295
  );
3022
- const onExperiment = useCallback5(
3296
+ const onExperiment = useCallback6(
3023
3297
  (e) => setExperimentId(e.currentTarget.value || null),
3024
3298
  []
3025
3299
  );
@@ -3192,14 +3466,14 @@ import {
3192
3466
  Stack as Stack13,
3193
3467
  Text as Text21
3194
3468
  } from "@sanity/ui";
3195
- import { useCallback as useCallback11, useEffect as useEffect6, useMemo as useMemo5, useState as useState6 } from "react";
3196
- import { useClient as useClient5 } from "sanity";
3469
+ import { useCallback as useCallback12, useEffect as useEffect7, useMemo as useMemo5, useState as useState7 } from "react";
3470
+ import { useClient as useClient6 } from "sanity";
3197
3471
 
3198
3472
  // src/components/content-filters/DocumentFilter.tsx
3199
3473
  import { SearchIcon as SearchIcon2 } from "@sanity/icons";
3200
3474
  import { Autocomplete as Autocomplete2, Badge as Badge4, Card as Card7, Flex as Flex8, Stack as Stack9, Text as Text12 } from "@sanity/ui";
3201
- import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
3202
- import { useClient as useClient3 } from "sanity";
3475
+ import { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
3476
+ import { useClient as useClient4 } from "sanity";
3203
3477
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3204
3478
  var SEARCH_DEBOUNCE_MS = 300;
3205
3479
  function DocumentFilter({
@@ -3207,16 +3481,16 @@ function DocumentFilter({
3207
3481
  onChange,
3208
3482
  onPerspectiveHint
3209
3483
  }) {
3210
- const client = useClient3({ apiVersion: API_VERSION });
3211
- const [options, setOptions] = useState3([]);
3212
- const [loading, setLoading] = useState3(false);
3213
- const timer = useRef2(null);
3214
- useEffect3(() => {
3484
+ const client = useClient4({ apiVersion: API_VERSION });
3485
+ const [options, setOptions] = useState4([]);
3486
+ const [loading, setLoading] = useState4(false);
3487
+ const timer = useRef3(null);
3488
+ useEffect4(() => {
3215
3489
  return () => {
3216
3490
  if (timer.current) clearTimeout(timer.current);
3217
3491
  };
3218
3492
  }, []);
3219
- const handleQueryChange = useCallback6(
3493
+ const handleQueryChange = useCallback7(
3220
3494
  (query) => {
3221
3495
  if (timer.current) clearTimeout(timer.current);
3222
3496
  const trimmed = (query ?? "").trim();
@@ -3260,7 +3534,7 @@ function DocumentFilter({
3260
3534
  },
3261
3535
  [client]
3262
3536
  );
3263
- const handleSelect = useCallback6(
3537
+ const handleSelect = useCallback7(
3264
3538
  (selected) => {
3265
3539
  const option = options.find((o) => o.value === selected);
3266
3540
  const slug = option?.payload.slug ?? selected;
@@ -3271,7 +3545,7 @@ function DocumentFilter({
3271
3545
  },
3272
3546
  [options, onChange, onPerspectiveHint]
3273
3547
  );
3274
- const renderOption = useCallback6((option) => {
3548
+ const renderOption = useCallback7((option) => {
3275
3549
  const { provenance, releaseId } = option.payload;
3276
3550
  const badgeTone = provenance === "published" ? "positive" : provenance === "release" ? "primary" : "caution";
3277
3551
  const badgeLabel = provenance === "published" ? "Published" : provenance === "release" ? releaseId ?? "Release" : "Draft";
@@ -3283,7 +3557,7 @@ function DocumentFilter({
3283
3557
  /* @__PURE__ */ jsx13(Badge4, { fontSize: 0, tone: badgeTone, children: badgeLabel })
3284
3558
  ] }) });
3285
3559
  }, []);
3286
- const renderValue = useCallback6((_value, option) => {
3560
+ const renderValue = useCallback7((_value, option) => {
3287
3561
  if (option?.payload.title) {
3288
3562
  return `${option.payload.title} (${option.payload.slug})`;
3289
3563
  }
@@ -3321,20 +3595,20 @@ function classifyDocId(id) {
3321
3595
  // src/components/content-filters/PerspectiveFilter.tsx
3322
3596
  import { SearchIcon as SearchIcon3 } from "@sanity/icons";
3323
3597
  import { Autocomplete as Autocomplete3, Badge as Badge5, Card as Card8, Flex as Flex9, Stack as Stack10, Text as Text13 } from "@sanity/ui";
3324
- import { useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
3598
+ import { useEffect as useEffect5, useMemo as useMemo4, useState as useState5 } from "react";
3325
3599
  import {
3326
3600
  getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId3,
3327
3601
  useActiveReleases as useActiveReleases3,
3328
3602
  useArchivedReleases as useArchivedReleases3,
3329
- useClient as useClient4
3603
+ useClient as useClient5
3330
3604
  } from "sanity";
3331
3605
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3332
3606
  function PerspectiveFilter({ value, onChange }) {
3333
- const client = useClient4({ apiVersion: API_VERSION });
3334
- const [reportPerspectives, setReportPerspectives] = useState4([]);
3607
+ const client = useClient5({ apiVersion: API_VERSION });
3608
+ const [reportPerspectives, setReportPerspectives] = useState5([]);
3335
3609
  const { data: activeReleases } = useActiveReleases3();
3336
3610
  const { data: archivedReleases } = useArchivedReleases3();
3337
- useEffect4(() => {
3611
+ useEffect5(() => {
3338
3612
  client.fetch(distinctPerspectivesQuery).then(
3339
3613
  (data) => setReportPerspectives((data ?? []).filter(Boolean).sort())
3340
3614
  ).catch(() => setReportPerspectives([]));
@@ -3402,7 +3676,7 @@ function PerspectiveFilter({ value, onChange }) {
3402
3676
 
3403
3677
  // src/components/report-card/ReportCard.tsx
3404
3678
  import { Badge as Badge10, Card as Card9, Flex as Flex13, Text as Text17 } from "@sanity/ui";
3405
- import { useCallback as useCallback7 } from "react";
3679
+ import { useCallback as useCallback8 } from "react";
3406
3680
 
3407
3681
  // src/components/primitives/DeltaIndicator.tsx
3408
3682
  import { Text as Text14 } from "@sanity/ui";
@@ -3609,7 +3883,7 @@ function StatusBadges({ regressed, improved }) {
3609
3883
  // src/components/report-card/ReportCard.tsx
3610
3884
  import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
3611
3885
  function ReportCard({ data, onSelectReport }) {
3612
- const handleClick = useCallback7(() => {
3886
+ const handleClick = useCallback8(() => {
3613
3887
  onSelectReport(data.reportId);
3614
3888
  }, [data.reportId, onSelectReport]);
3615
3889
  return /* @__PURE__ */ jsx20(
@@ -3649,10 +3923,10 @@ function ReportCard({ data, onSelectReport }) {
3649
3923
  import { SearchIcon as SearchIcon4 } from "@sanity/icons";
3650
3924
  import { Card as Card11, Flex as Flex16, Text as Text20 } from "@sanity/ui";
3651
3925
  import {
3652
- useCallback as useCallback10,
3653
- useEffect as useEffect5,
3654
- useRef as useRef3,
3655
- useState as useState5
3926
+ useCallback as useCallback11,
3927
+ useEffect as useEffect6,
3928
+ useRef as useRef4,
3929
+ useState as useState6
3656
3930
  } from "react";
3657
3931
 
3658
3932
  // src/components/search-bar/types.ts
@@ -3793,12 +4067,12 @@ function filterAndExclude(values, query, dim, activeTokens) {
3793
4067
  // src/components/search-bar/FilterBadge.tsx
3794
4068
  import { CloseIcon } from "@sanity/icons";
3795
4069
  import { Badge as Badge11, Flex as Flex14, Text as Text18 } from "@sanity/ui";
3796
- import { useCallback as useCallback8 } from "react";
4070
+ import { useCallback as useCallback9 } from "react";
3797
4071
  import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
3798
4072
  function FilterBadge({ token, onRemove }) {
3799
4073
  const dim = DIMENSIONS.find((d) => d.key === token.dimension);
3800
4074
  const tone = dim?.tone ?? "default";
3801
- const handleRemove = useCallback8(
4075
+ const handleRemove = useCallback9(
3802
4076
  (e) => {
3803
4077
  e.stopPropagation();
3804
4078
  onRemove(token.id);
@@ -3838,7 +4112,7 @@ function FilterBadge({ token, onRemove }) {
3838
4112
 
3839
4113
  // src/components/search-bar/SuggestionList.tsx
3840
4114
  import { Badge as Badge12, Card as Card10, Flex as Flex15, Stack as Stack12, Text as Text19 } from "@sanity/ui";
3841
- import { useCallback as useCallback9 } from "react";
4115
+ import { useCallback as useCallback10 } from "react";
3842
4116
  import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
3843
4117
  function SuggestionList({
3844
4118
  suggestions,
@@ -3902,7 +4176,7 @@ function SuggestionItem({
3902
4176
  const dim = DIMENSIONS.find((d) => d.key === suggestion.dimension);
3903
4177
  const tone = dim?.tone ?? "default";
3904
4178
  const isHint = suggestion.category === "Filters";
3905
- const handleClick = useCallback9(() => {
4179
+ const handleClick = useCallback10(() => {
3906
4180
  onSelect(suggestion);
3907
4181
  }, [onSelect, suggestion]);
3908
4182
  return /* @__PURE__ */ jsx22(
@@ -3940,11 +4214,11 @@ function SearchBar({
3940
4214
  onTokenAdd,
3941
4215
  onTokenRemove
3942
4216
  }) {
3943
- const [focused, setFocused] = useState5(false);
3944
- const [activeIndex, setActiveIndex] = useState5(-1);
3945
- const inputRef = useRef3(null);
3946
- const blurTimerRef = useRef3(null);
3947
- useEffect5(() => {
4217
+ const [focused, setFocused] = useState6(false);
4218
+ const [activeIndex, setActiveIndex] = useState6(-1);
4219
+ const inputRef = useRef4(null);
4220
+ const blurTimerRef = useRef4(null);
4221
+ useEffect6(() => {
3948
4222
  return () => {
3949
4223
  if (blurTimerRef.current) {
3950
4224
  clearTimeout(blurTimerRef.current);
@@ -3952,10 +4226,10 @@ function SearchBar({
3952
4226
  };
3953
4227
  }, []);
3954
4228
  const suggestions = focused ? computeSuggestions({ query, activeTokens: tokens, models, areas }) : [];
3955
- useEffect5(() => {
4229
+ useEffect6(() => {
3956
4230
  setActiveIndex(-1);
3957
4231
  }, [query, tokens.length]);
3958
- const handleTokenRemove = useCallback10(
4232
+ const handleTokenRemove = useCallback11(
3959
4233
  (id) => {
3960
4234
  onTokenRemove(id);
3961
4235
  requestAnimationFrame(() => {
@@ -3964,7 +4238,7 @@ function SearchBar({
3964
4238
  },
3965
4239
  [onTokenRemove]
3966
4240
  );
3967
- const handleSuggestionSelect = useCallback10(
4241
+ const handleSuggestionSelect = useCallback11(
3968
4242
  (suggestion) => {
3969
4243
  if (suggestion.category === "Filters") {
3970
4244
  onQueryChange(suggestion.value);
@@ -3983,7 +4257,7 @@ function SearchBar({
3983
4257
  },
3984
4258
  [onTokenAdd, onQueryChange]
3985
4259
  );
3986
- const handleKeyDown = useCallback10(
4260
+ const handleKeyDown = useCallback11(
3987
4261
  (e) => {
3988
4262
  if (e.key === "ArrowDown") {
3989
4263
  e.preventDefault();
@@ -4011,27 +4285,27 @@ function SearchBar({
4011
4285
  handleSuggestionSelect
4012
4286
  ]
4013
4287
  );
4014
- const handleInputChange = useCallback10(
4288
+ const handleInputChange = useCallback11(
4015
4289
  (e) => {
4016
4290
  const value = e.target.value;
4017
4291
  onQueryChange(value);
4018
4292
  },
4019
4293
  [onQueryChange]
4020
4294
  );
4021
- const handleBlur = useCallback10(() => {
4295
+ const handleBlur = useCallback11(() => {
4022
4296
  blurTimerRef.current = setTimeout(() => {
4023
4297
  blurTimerRef.current = null;
4024
4298
  setFocused(false);
4025
4299
  }, 200);
4026
4300
  }, []);
4027
- const handleFocus = useCallback10(() => {
4301
+ const handleFocus = useCallback11(() => {
4028
4302
  if (blurTimerRef.current) {
4029
4303
  clearTimeout(blurTimerRef.current);
4030
4304
  blurTimerRef.current = null;
4031
4305
  }
4032
4306
  setFocused(true);
4033
4307
  }, []);
4034
- const handleBarClick = useCallback10(() => {
4308
+ const handleBarClick = useCallback11(() => {
4035
4309
  inputRef.current?.focus();
4036
4310
  }, []);
4037
4311
  return /* @__PURE__ */ jsxs20("div", { style: { position: "relative" }, children: [
@@ -4104,22 +4378,22 @@ function LatestReports({
4104
4378
  pageSize = 20,
4105
4379
  source = null
4106
4380
  }) {
4107
- const client = useClient5({ apiVersion: API_VERSION });
4108
- const [initialLoading, setInitialLoading] = useState6(true);
4109
- const [loadingMore, setLoadingMore] = useState6(false);
4110
- const [reports, setReports] = useState6([]);
4111
- const [hasMore, setHasMore] = useState6(true);
4112
- const [searchQuery, setSearchQuery] = useState6("");
4113
- const [filterTokens, setFilterTokens] = useState6([]);
4114
- const [documentSlug, setDocumentSlug] = useState6("");
4115
- const [perspective, setPerspective] = useState6("");
4116
- const [sort, setSort] = useState6({
4381
+ const client = useClient6({ apiVersion: API_VERSION });
4382
+ const [initialLoading, setInitialLoading] = useState7(true);
4383
+ const [loadingMore, setLoadingMore] = useState7(false);
4384
+ const [reports, setReports] = useState7([]);
4385
+ const [hasMore, setHasMore] = useState7(true);
4386
+ const [searchQuery, setSearchQuery] = useState7("");
4387
+ const [filterTokens, setFilterTokens] = useState7([]);
4388
+ const [documentSlug, setDocumentSlug] = useState7("");
4389
+ const [perspective, setPerspective] = useState7("");
4390
+ const [sort, setSort] = useState7({
4117
4391
  direction: "desc",
4118
4392
  field: "date"
4119
4393
  });
4120
- const [availableModels, setAvailableModels] = useState6([]);
4121
- const [availableAreas, setAvailableAreas] = useState6([]);
4122
- useEffect6(() => {
4394
+ const [availableModels, setAvailableModels] = useState7([]);
4395
+ const [availableAreas, setAvailableAreas] = useState7([]);
4396
+ useEffect7(() => {
4123
4397
  setInitialLoading(true);
4124
4398
  setHasMore(true);
4125
4399
  client.fetch(latestReportsQuery, {
@@ -4137,7 +4411,7 @@ function LatestReports({
4137
4411
  setInitialLoading(false);
4138
4412
  });
4139
4413
  }, [client, pageSize, mode, source]);
4140
- const handleLoadMore = useCallback11(() => {
4414
+ const handleLoadMore = useCallback12(() => {
4141
4415
  if (loadingMore || !hasMore) return;
4142
4416
  setLoadingMore(true);
4143
4417
  const nextLimit = reports.length + pageSize;
@@ -4154,7 +4428,7 @@ function LatestReports({
4154
4428
  setLoadingMore(false);
4155
4429
  });
4156
4430
  }, [client, hasMore, loadingMore, mode, pageSize, reports.length, source]);
4157
- useEffect6(() => {
4431
+ useEffect7(() => {
4158
4432
  client.fetch(distinctModelsQuery).then((data) => setAvailableModels((data ?? []).sort())).catch(() => setAvailableModels([]));
4159
4433
  client.fetch(distinctAreasQuery).then((data) => setAvailableAreas((data ?? []).sort())).catch(() => setAvailableAreas([]));
4160
4434
  }, [client]);
@@ -4238,7 +4512,7 @@ function LatestReports({
4238
4512
  });
4239
4513
  return result;
4240
4514
  }, [reports, searchQuery, activeFilters, documentSlug, perspective, sort]);
4241
- const handleTokenAdd = useCallback11((token) => {
4515
+ const handleTokenAdd = useCallback12((token) => {
4242
4516
  setFilterTokens((prev) => {
4243
4517
  const dim = token.dimension;
4244
4518
  const isMulti = dim === "area";
@@ -4248,22 +4522,22 @@ function LatestReports({
4248
4522
  return [...prev, token];
4249
4523
  });
4250
4524
  }, []);
4251
- const handleTokenRemove = useCallback11((id) => {
4525
+ const handleTokenRemove = useCallback12((id) => {
4252
4526
  setFilterTokens((prev) => prev.filter((t) => t.id !== id));
4253
4527
  }, []);
4254
- const toggleSortDirection = useCallback11(() => {
4528
+ const toggleSortDirection = useCallback12(() => {
4255
4529
  setSort((prev) => ({
4256
4530
  ...prev,
4257
4531
  direction: prev.direction === "asc" ? "desc" : "asc"
4258
4532
  }));
4259
4533
  }, []);
4260
- const handleSortFieldChange = useCallback11((field) => {
4534
+ const handleSortFieldChange = useCallback12((field) => {
4261
4535
  setSort(
4262
4536
  (prev) => prev.field === field ? { ...prev, direction: prev.direction === "asc" ? "desc" : "asc" } : { direction: "desc", field }
4263
4537
  );
4264
4538
  }, []);
4265
4539
  const hasActiveFilters = searchQuery.trim() !== "" || filterTokens.length > 0 || documentSlug.trim() !== "" || perspective.trim() !== "";
4266
- const handleClearFilters = useCallback11(() => {
4540
+ const handleClearFilters = useCallback12(() => {
4267
4541
  setSearchQuery("");
4268
4542
  setFilterTokens([]);
4269
4543
  setDocumentSlug("");
@@ -4471,15 +4745,15 @@ import {
4471
4745
  Tooltip as Tooltip9
4472
4746
  } from "@sanity/ui";
4473
4747
  import {
4474
- useCallback as useCallback12,
4475
- useEffect as useEffect7,
4748
+ useCallback as useCallback13,
4749
+ useEffect as useEffect8,
4476
4750
  useMemo as useMemo7,
4477
- useState as useState9
4751
+ useState as useState10
4478
4752
  } from "react";
4479
- import { useClient as useClient6 } from "sanity";
4753
+ import { useClient as useClient7 } from "sanity";
4480
4754
 
4481
4755
  // src/components/report-detail/AgentActivitySection.tsx
4482
- import { useMemo as useMemo6, useState as useState7 } from "react";
4756
+ import { useMemo as useMemo6, useState as useState8 } from "react";
4483
4757
  import { HelpCircleIcon as HelpCircleIcon5, SearchIcon as SearchIcon5 } from "@sanity/icons";
4484
4758
  import {
4485
4759
  Badge as Badge14,
@@ -4654,7 +4928,7 @@ function FeatureActivityCard({
4654
4928
  ] }) });
4655
4929
  }
4656
4930
  function SearchQueryList({ queries }) {
4657
- const [filter, setFilter] = useState7("");
4931
+ const [filter, setFilter] = useState8("");
4658
4932
  const filtered = useMemo6(() => {
4659
4933
  if (!filter) return queries;
4660
4934
  const lower = filter.toLowerCase();
@@ -4958,7 +5232,7 @@ function AreaBadgeGroup({
4958
5232
  }
4959
5233
 
4960
5234
  // src/components/report-detail/JudgmentList.tsx
4961
- import { useState as useState8 } from "react";
5235
+ import { useState as useState9 } from "react";
4962
5236
  import { HelpCircleIcon as HelpCircleIcon6 } from "@sanity/icons";
4963
5237
  import { Badge as Badge16, Box as Box12, Card as Card18, Flex as Flex20, Stack as Stack18, Text as Text27, Tooltip as Tooltip6 } from "@sanity/ui";
4964
5238
 
@@ -5033,7 +5307,7 @@ function JudgmentList({ judgments }) {
5033
5307
  ] }) });
5034
5308
  }
5035
5309
  function JudgmentCard({ judgment }) {
5036
- const [expanded, setExpanded] = useState8(false);
5310
+ const [expanded, setExpanded] = useState9(false);
5037
5311
  const dimLabel = DIMENSION_LABELS[judgment.dimension] ?? judgment.dimension;
5038
5312
  const sep = judgment.taskId.indexOf(" - ");
5039
5313
  const taskName = sep > 0 ? judgment.taskId.substring(sep + 3) : judgment.taskId;
@@ -5090,7 +5364,7 @@ var editLinkStyle = {
5090
5364
  function DocBadge({
5091
5365
  doc
5092
5366
  }) {
5093
- const [hovered, setHovered] = useState8(false);
5367
+ const [hovered, setHovered] = useState9(false);
5094
5368
  const isLinked = Boolean(doc.documentId);
5095
5369
  const tooltipLabel = isLinked ? `Edit "${doc.title || doc.slug}"` : doc.title || doc.slug;
5096
5370
  const badge = /* @__PURE__ */ jsx31(Badge16, { mode: "outline", tone: isLinked && hovered ? "caution" : "primary", children: doc.slug });
@@ -5672,10 +5946,10 @@ function ReportDetail({
5672
5946
  onTabChange,
5673
5947
  reportId
5674
5948
  }) {
5675
- const client = useClient6({ apiVersion: API_VERSION });
5676
- const [loading, setLoading] = useState9(true);
5677
- const [report, setReport] = useState9(null);
5678
- useEffect7(() => {
5949
+ const client = useClient7({ apiVersion: API_VERSION });
5950
+ const [loading, setLoading] = useState10(true);
5951
+ const [report, setReport] = useState10(null);
5952
+ useEffect8(() => {
5679
5953
  let cancelled = false;
5680
5954
  setLoading(true);
5681
5955
  client.fetch(reportDetailQuery, { reportId }).then((data) => {
@@ -5690,7 +5964,7 @@ function ReportDetail({
5690
5964
  cancelled = true;
5691
5965
  };
5692
5966
  }, [client, reportId]);
5693
- const handleCopyReportId = useCallback12(() => {
5967
+ const handleCopyReportId = useCallback13(() => {
5694
5968
  if (!report) return;
5695
5969
  navigator.clipboard.writeText(report.reportId).catch(() => {
5696
5970
  });
@@ -5717,7 +5991,7 @@ function ReportDetail({
5717
5991
  if (disabledTabs.has(parsed)) return "overview";
5718
5992
  return tabs.some((t) => t.id === parsed) ? parsed : "overview";
5719
5993
  }, [activeTab, disabledTabs, tabs]);
5720
- const handleTabClick = useCallback12(
5994
+ const handleTabClick = useCallback13(
5721
5995
  (tabId) => {
5722
5996
  onTabChange(tabId === "overview" ? null : tabId);
5723
5997
  },
@@ -5867,8 +6141,8 @@ function getDisabledTabTooltip(tabId, summary) {
5867
6141
 
5868
6142
  // src/components/ScoreTimeline.tsx
5869
6143
  import { Card as Card23, Flex as Flex25, Select as Select2, Stack as Stack24, Text as Text33 } from "@sanity/ui";
5870
- import { useCallback as useCallback13, useEffect as useEffect8, useMemo as useMemo8, useState as useState10 } from "react";
5871
- import { useClient as useClient7 } from "sanity";
6144
+ import { useCallback as useCallback14, useEffect as useEffect9, useMemo as useMemo8, useState as useState11 } from "react";
6145
+ import { useClient as useClient8 } from "sanity";
5872
6146
  import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
5873
6147
  var CHART_HEIGHT = 220;
5874
6148
  var CHART_WIDTH = 800;
@@ -5903,11 +6177,11 @@ function scoreForPoint(point, area) {
5903
6177
  return match?.totalScore ?? null;
5904
6178
  }
5905
6179
  function ScoreTimeline({ mode = null, source = null }) {
5906
- const client = useClient7({ apiVersion: API_VERSION });
5907
- const [dataPoints, setDataPoints] = useState10([]);
5908
- const [loading, setLoading] = useState10(true);
5909
- const [rangeDays, setRangeDays] = useState10(30);
5910
- const [selectedArea, setSelectedArea] = useState10(null);
6180
+ const client = useClient8({ apiVersion: API_VERSION });
6181
+ const [dataPoints, setDataPoints] = useState11([]);
6182
+ const [loading, setLoading] = useState11(true);
6183
+ const [rangeDays, setRangeDays] = useState11(30);
6184
+ const [selectedArea, setSelectedArea] = useState11(null);
5911
6185
  const areaNames = useMemo8(() => {
5912
6186
  const names = /* @__PURE__ */ new Set();
5913
6187
  for (const dp of dataPoints) {
@@ -5917,7 +6191,7 @@ function ScoreTimeline({ mode = null, source = null }) {
5917
6191
  }
5918
6192
  return Array.from(names).sort();
5919
6193
  }, [dataPoints]);
5920
- const fetchData = useCallback13(async () => {
6194
+ const fetchData = useCallback14(async () => {
5921
6195
  setLoading(true);
5922
6196
  try {
5923
6197
  const startDate = rangeDays ? daysAgo(rangeDays) : "1970-01-01T00:00:00Z";
@@ -5932,7 +6206,7 @@ function ScoreTimeline({ mode = null, source = null }) {
5932
6206
  setLoading(false);
5933
6207
  }
5934
6208
  }, [client, mode, rangeDays, source]);
5935
- useEffect8(() => {
6209
+ useEffect9(() => {
5936
6210
  void fetchData();
5937
6211
  }, [fetchData]);
5938
6212
  const chartPoints = useMemo8(() => {
@@ -5953,14 +6227,14 @@ function ScoreTimeline({ mode = null, source = null }) {
5953
6227
  if (chartPoints.length === 0) return 0;
5954
6228
  return chartPoints.reduce((sum, p) => sum + p.score, 0) / chartPoints.length;
5955
6229
  }, [chartPoints]);
5956
- const handleRangeChange = useCallback13(
6230
+ const handleRangeChange = useCallback14(
5957
6231
  (e) => {
5958
6232
  const val = e.currentTarget.value;
5959
6233
  setRangeDays(val === "all" ? null : Number(val));
5960
6234
  },
5961
6235
  []
5962
6236
  );
5963
- const handleAreaChange = useCallback13(
6237
+ const handleAreaChange = useCallback14(
5964
6238
  (e) => {
5965
6239
  const val = e.currentTarget.value;
5966
6240
  setSelectedArea(val || null);
@@ -6093,13 +6367,13 @@ var VIEW_PARAM_MAP = {
6093
6367
  timeline: "timeline"
6094
6368
  };
6095
6369
  function Dashboard() {
6096
- const client = useClient8({ apiVersion: API_VERSION });
6370
+ const client = useClient9({ apiVersion: API_VERSION });
6097
6371
  const router = useRouter();
6098
6372
  const routerState = router.state;
6099
6373
  const reportId = routerState.reportId ?? null;
6100
6374
  const isDetail = reportId !== null;
6101
6375
  const activeTab = isDetail ? "latest" : VIEW_PARAM_MAP[routerState.view ?? ""] ?? "latest";
6102
- const navigateToTab = useCallback14(
6376
+ const navigateToTab = useCallback15(
6103
6377
  (tab) => {
6104
6378
  if (tab === "latest") {
6105
6379
  router.navigate({});
@@ -6109,13 +6383,13 @@ function Dashboard() {
6109
6383
  },
6110
6384
  [router]
6111
6385
  );
6112
- const handleSelectReport = useCallback14(
6386
+ const handleSelectReport = useCallback15(
6113
6387
  (id) => {
6114
6388
  router.navigate({ reportId: id });
6115
6389
  },
6116
6390
  [router]
6117
6391
  );
6118
- const handleTabChange = useCallback14(
6392
+ const handleTabChange = useCallback15(
6119
6393
  (tab) => {
6120
6394
  if (!routerState.reportId) return;
6121
6395
  if (tab) {
@@ -6126,14 +6400,14 @@ function Dashboard() {
6126
6400
  },
6127
6401
  [router, routerState.reportId]
6128
6402
  );
6129
- const handleBack = useCallback14(() => {
6403
+ const handleBack = useCallback15(() => {
6130
6404
  router.navigate({});
6131
6405
  }, [router]);
6132
- const [source, setSource] = useState11(null);
6133
- const [mode, setMode] = useState11(null);
6134
- const [sources, setSources] = useState11([]);
6135
- const [modes, setModes] = useState11([]);
6136
- useEffect9(() => {
6406
+ const [source, setSource] = useState12(null);
6407
+ const [mode, setMode] = useState12(null);
6408
+ const [sources, setSources] = useState12([]);
6409
+ const [modes, setModes] = useState12([]);
6410
+ useEffect10(() => {
6137
6411
  client.fetch(distinctSourcesQuery).then((data) => setSources(data ?? [])).catch(() => setSources([]));
6138
6412
  client.fetch(distinctModesQuery).then((data) => setModes(data ?? [])).catch(() => setModes([]));
6139
6413
  }, [client]);
@@ -6241,23 +6515,23 @@ function ailfTool(options = {}) {
6241
6515
 
6242
6516
  // src/actions/RunEvaluationAction.tsx
6243
6517
  import { BarChartIcon as BarChartIcon2 } from "@sanity/icons";
6244
- import { useToast } from "@sanity/ui";
6245
- import { useCallback as useCallback15, useEffect as useEffect10, useRef as useRef4, useState as useState12 } from "react";
6518
+ import { useToast as useToast2 } from "@sanity/ui";
6519
+ import { useCallback as useCallback16, useEffect as useEffect11, useRef as useRef5, useState as useState13 } from "react";
6246
6520
  import {
6247
6521
  getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId4,
6248
- useClient as useClient9,
6249
- useCurrentUser,
6250
- useDataset,
6251
- useProjectId
6522
+ useClient as useClient10,
6523
+ useCurrentUser as useCurrentUser2,
6524
+ useDataset as useDataset2,
6525
+ useProjectId as useProjectId2
6252
6526
  } from "sanity";
6253
6527
  var API_VERSION2 = "2026-03-11";
6254
- var EVAL_REQUEST_TYPE = "ailf.evalRequest";
6255
- var POLL_INTERVAL_MS = 3e4;
6256
- var MAX_POLL_MS = 30 * 60 * 1e3;
6257
- var EVAL_REQUEST_STATUS_QUERY = (
6528
+ var EVAL_REQUEST_TYPE2 = "ailf.evalRequest";
6529
+ var POLL_INTERVAL_MS2 = 3e4;
6530
+ var MAX_POLL_MS2 = 30 * 60 * 1e3;
6531
+ var EVAL_REQUEST_STATUS_QUERY2 = (
6258
6532
  /* groq */
6259
6533
  `
6260
- *[_type == "${EVAL_REQUEST_TYPE}" && _id == $id][0] {
6534
+ *[_type == "${EVAL_REQUEST_TYPE2}" && _id == $id][0] {
6261
6535
  status,
6262
6536
  error,
6263
6537
  reportId
@@ -6268,15 +6542,15 @@ function createRunEvaluationAction(options = {}) {
6268
6542
  const { mode = "baseline" } = options;
6269
6543
  const RunEvaluationAction = (props) => {
6270
6544
  const { release } = props;
6271
- const client = useClient9({ apiVersion: API_VERSION2 });
6272
- const dataset = useDataset();
6273
- const projectId = useProjectId();
6274
- const currentUser = useCurrentUser();
6275
- const toast = useToast();
6276
- const [state, setState] = useState12({ status: "loading" });
6277
- const requestedAtRef = useRef4(null);
6545
+ const client = useClient10({ apiVersion: API_VERSION2 });
6546
+ const dataset = useDataset2();
6547
+ const projectId = useProjectId2();
6548
+ const currentUser = useCurrentUser2();
6549
+ const toast = useToast2();
6550
+ const [state, setState] = useState13({ status: "loading" });
6551
+ const requestedAtRef = useRef5(null);
6278
6552
  const perspectiveId = getReleaseIdFromReleaseDocumentId4(release._id);
6279
- useEffect10(() => {
6553
+ useEffect11(() => {
6280
6554
  let cancelled = false;
6281
6555
  client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
6282
6556
  if (cancelled) return;
@@ -6299,14 +6573,14 @@ function createRunEvaluationAction(options = {}) {
6299
6573
  cancelled = true;
6300
6574
  };
6301
6575
  }, [client, perspectiveId]);
6302
- useEffect10(() => {
6576
+ useEffect11(() => {
6303
6577
  if (state.status !== "requested" && state.status !== "polling") return;
6304
6578
  const { requestId, startedAt } = state;
6305
6579
  if (state.status === "requested") {
6306
6580
  setState({ requestId, startedAt, status: "polling" });
6307
6581
  }
6308
6582
  const interval = setInterval(async () => {
6309
- if (Date.now() - startedAt > MAX_POLL_MS) {
6583
+ if (Date.now() - startedAt > MAX_POLL_MS2) {
6310
6584
  clearInterval(interval);
6311
6585
  setState({
6312
6586
  message: "Evaluation is still running. Check the AI Literacy dashboard for results.",
@@ -6315,7 +6589,7 @@ function createRunEvaluationAction(options = {}) {
6315
6589
  return;
6316
6590
  }
6317
6591
  try {
6318
- const reqStatus = await client.fetch(EVAL_REQUEST_STATUS_QUERY, {
6592
+ const reqStatus = await client.fetch(EVAL_REQUEST_STATUS_QUERY2, {
6319
6593
  id: requestId
6320
6594
  });
6321
6595
  if (reqStatus?.status === "failed") {
@@ -6346,10 +6620,10 @@ function createRunEvaluationAction(options = {}) {
6346
6620
  }
6347
6621
  } catch {
6348
6622
  }
6349
- }, POLL_INTERVAL_MS);
6623
+ }, POLL_INTERVAL_MS2);
6350
6624
  return () => clearInterval(interval);
6351
6625
  }, [client, perspectiveId, state]);
6352
- useEffect10(() => {
6626
+ useEffect11(() => {
6353
6627
  if (state.status !== "error") return;
6354
6628
  const timer = setTimeout(() => {
6355
6629
  client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
@@ -6369,13 +6643,13 @@ function createRunEvaluationAction(options = {}) {
6369
6643
  }, 15e3);
6370
6644
  return () => clearTimeout(timer);
6371
6645
  }, [client, perspectiveId, state]);
6372
- const handleRequest = useCallback15(async () => {
6646
+ const handleRequest = useCallback16(async () => {
6373
6647
  const releaseTitle = release.metadata?.title ?? perspectiveId ?? "release";
6374
- const tag = `release-${slugify(releaseTitle)}-${dateStamp()}`;
6648
+ const tag = `release-${slugify2(releaseTitle)}-${dateStamp2()}`;
6375
6649
  const now = Date.now();
6376
6650
  try {
6377
6651
  const doc = await client.create({
6378
- _type: EVAL_REQUEST_TYPE,
6652
+ _type: EVAL_REQUEST_TYPE2,
6379
6653
  dataset,
6380
6654
  mode,
6381
6655
  perspective: perspectiveId,
@@ -6415,15 +6689,15 @@ function createRunEvaluationAction(options = {}) {
6415
6689
  return {
6416
6690
  disabled: state.status === "loading" || state.status === "requested" || state.status === "polling",
6417
6691
  icon: BarChartIcon2,
6418
- label: getLabel(state),
6692
+ label: getLabel2(state),
6419
6693
  onHandle: handleRequest,
6420
- title: getTitle(state, perspectiveId)
6694
+ title: getTitle2(state, perspectiveId)
6421
6695
  };
6422
6696
  };
6423
6697
  RunEvaluationAction.displayName = "RunEvaluationAction";
6424
6698
  return RunEvaluationAction;
6425
6699
  }
6426
- function getLabel(state) {
6700
+ function getLabel2(state) {
6427
6701
  switch (state.status) {
6428
6702
  case "loading":
6429
6703
  return "AI Eval";
@@ -6441,7 +6715,7 @@ function getLabel(state) {
6441
6715
  return "Eval Failed";
6442
6716
  }
6443
6717
  }
6444
- function getTitle(state, perspectiveId) {
6718
+ function getTitle2(state, perspectiveId) {
6445
6719
  switch (state.status) {
6446
6720
  case "loading":
6447
6721
  return "Checking for existing evaluation results\u2026";
@@ -6469,10 +6743,10 @@ function buildReportQueryParams(perspectiveId) {
6469
6743
  source: null
6470
6744
  };
6471
6745
  }
6472
- function slugify(s) {
6746
+ function slugify2(s) {
6473
6747
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
6474
6748
  }
6475
- function dateStamp() {
6749
+ function dateStamp2() {
6476
6750
  const d = /* @__PURE__ */ new Date();
6477
6751
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
6478
6752
  }
@@ -6483,7 +6757,7 @@ var ailfPlugin = definePlugin({
6483
6757
  document: {
6484
6758
  actions: (prev, context) => {
6485
6759
  if (context.schemaType === "ailf.task") {
6486
- return [...prev, GraduateToNativeAction];
6760
+ return [...prev, GraduateToNativeAction, RunTaskEvaluationAction];
6487
6761
  }
6488
6762
  return prev;
6489
6763
  }
@@ -6507,6 +6781,7 @@ export {
6507
6781
  GraduateToNativeAction,
6508
6782
  MirrorBanner,
6509
6783
  ReleasePicker,
6784
+ RunTaskEvaluationAction,
6510
6785
  SyncStatusBadge,
6511
6786
  ailfPlugin,
6512
6787
  ailfTool,