@burdenoff/microfe-atheletebridge 2026.801.2 → 2026.801.3

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 (63) hide show
  1. package/dist/atheletebridge/AthleteBridgeRoot.d.ts.map +1 -1
  2. package/dist/atheletebridge/AthleteBridgeRoot.js +53 -45
  3. package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
  4. package/dist/atheletebridge/AthleteBridgeRoutes.d.ts.map +1 -1
  5. package/dist/atheletebridge/AthleteBridgeRoutes.js +15 -7
  6. package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
  7. package/dist/atheletebridge/components/StatusBadge.d.ts.map +1 -1
  8. package/dist/atheletebridge/components/StatusBadge.js +3 -1
  9. package/dist/atheletebridge/components/StatusBadge.js.map +1 -1
  10. package/dist/atheletebridge/components/ai/AgentRunFeed.d.ts +19 -0
  11. package/dist/atheletebridge/components/ai/AgentRunFeed.d.ts.map +1 -0
  12. package/dist/atheletebridge/components/ai/AgentRunFeed.js +124 -0
  13. package/dist/atheletebridge/components/ai/AgentRunFeed.js.map +1 -0
  14. package/dist/atheletebridge/components/ai/AiErrorNotice.d.ts +21 -0
  15. package/dist/atheletebridge/components/ai/AiErrorNotice.d.ts.map +1 -0
  16. package/dist/atheletebridge/components/ai/AiErrorNotice.js +114 -0
  17. package/dist/atheletebridge/components/ai/AiErrorNotice.js.map +1 -0
  18. package/dist/atheletebridge/components/ai/AiModelPicker.d.ts +19 -0
  19. package/dist/atheletebridge/components/ai/AiModelPicker.d.ts.map +1 -0
  20. package/dist/atheletebridge/components/ai/AiModelPicker.js +203 -0
  21. package/dist/atheletebridge/components/ai/AiModelPicker.js.map +1 -0
  22. package/dist/atheletebridge/components/ai/DecisionCard.d.ts +11 -0
  23. package/dist/atheletebridge/components/ai/DecisionCard.d.ts.map +1 -0
  24. package/dist/atheletebridge/components/ai/DecisionCard.js +343 -0
  25. package/dist/atheletebridge/components/ai/DecisionCard.js.map +1 -0
  26. package/dist/atheletebridge/components/ai/RunDecisionPanel.d.ts +21 -0
  27. package/dist/atheletebridge/components/ai/RunDecisionPanel.d.ts.map +1 -0
  28. package/dist/atheletebridge/components/ai/RunDecisionPanel.js +371 -0
  29. package/dist/atheletebridge/components/ai/RunDecisionPanel.js.map +1 -0
  30. package/dist/atheletebridge/components/ai/assessment.d.ts +14 -0
  31. package/dist/atheletebridge/components/ai/assessment.d.ts.map +1 -0
  32. package/dist/atheletebridge/components/ai/assessment.js +30 -0
  33. package/dist/atheletebridge/components/ai/assessment.js.map +1 -0
  34. package/dist/atheletebridge/components/ai/index.d.ts +11 -0
  35. package/dist/atheletebridge/components/ai/index.d.ts.map +1 -0
  36. package/dist/atheletebridge/components/index.d.ts +1 -0
  37. package/dist/atheletebridge/components/index.d.ts.map +1 -1
  38. package/dist/atheletebridge/hooks/index.d.ts +2 -2
  39. package/dist/atheletebridge/hooks/index.d.ts.map +1 -1
  40. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts +92 -1
  41. package/dist/atheletebridge/hooks/useAthleteBridgeApi.d.ts.map +1 -1
  42. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +274 -129
  43. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  44. package/dist/atheletebridge/index.d.ts +1 -1
  45. package/dist/atheletebridge/index.d.ts.map +1 -1
  46. package/dist/atheletebridge/pages/ai/AiOperationsPage.d.ts +23 -0
  47. package/dist/atheletebridge/pages/ai/AiOperationsPage.d.ts.map +1 -0
  48. package/dist/atheletebridge/pages/ai/AiOperationsPage.js +117 -0
  49. package/dist/atheletebridge/pages/ai/AiOperationsPage.js.map +1 -0
  50. package/dist/atheletebridge/types/index.d.ts +124 -1
  51. package/dist/atheletebridge/types/index.d.ts.map +1 -1
  52. package/dist/atheletebridge/utils/aiDecision.d.ts +73 -0
  53. package/dist/atheletebridge/utils/aiDecision.d.ts.map +1 -0
  54. package/dist/atheletebridge/utils/aiDecision.js +187 -0
  55. package/dist/atheletebridge/utils/aiDecision.js.map +1 -0
  56. package/dist/atheletebridge/utils/index.d.ts +2 -0
  57. package/dist/atheletebridge/utils/index.d.ts.map +1 -1
  58. package/dist/atheletebridge/utils/pageContext.d.ts.map +1 -1
  59. package/dist/atheletebridge/utils/pageContext.js +5 -0
  60. package/dist/atheletebridge/utils/pageContext.js.map +1 -1
  61. package/dist/generated/wspace-types.d.ts +68885 -33499
  62. package/dist/generated/wspace-types.d.ts.map +1 -1
  63. package/package.json +1 -1
@@ -0,0 +1,343 @@
1
+ import { cn as e } from "../../utils/cn.js";
2
+ import { StatusBadge as t } from "../StatusBadge.js";
3
+ import { formatDate as n } from "../../utils/formatters.js";
4
+ import { useOverrideAgentRun as r, useProgramAiState as i, usePrograms as a } from "../../hooks/useAthleteBridgeApi.js";
5
+ import { timeAgo as o } from "../../utils/timeAgo.js";
6
+ import { FormField as s, fieldInputClass as c } from "../form.js";
7
+ import { AiErrorNotice as l } from "./AiErrorNotice.js";
8
+ import { formatConfidence as u, formatLoadChange as d, isRecord as f, programIdFromInputRefs as p, summarizeDecision as m, toProvenanceEntries as h } from "../../utils/aiDecision.js";
9
+ import { ADJUSTMENT_STATUS_LABELS as g, ASSESSMENT_DESCRIPTIONS as _, ASSESSMENT_LABELS as v, ASSESSMENT_OPTIONS as y, ASSESSMENT_VARIANT as b } from "./assessment.js";
10
+ import { useState as x } from "react";
11
+ import { AlertTriangle as S, Check as C, FileSearch as w, Gavel as T, Loader2 as E } from "lucide-react";
12
+ import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
13
+ import { Badge as A, GlassCard as j } from "@burdenoff/fe-libs/ui";
14
+ //#region src/atheletebridge/components/ai/DecisionCard.tsx
15
+ function M({ programId: e }) {
16
+ let n = i(e);
17
+ if (n.isLoading) return /* @__PURE__ */ k("p", {
18
+ className: "inline-flex items-center gap-1.5 text-xs text-text-muted",
19
+ children: [/* @__PURE__ */ O(E, { className: "h-3 w-3 animate-spin" }), " Loading program state…"]
20
+ });
21
+ if (n.isError || !n.data) return /* @__PURE__ */ k("p", {
22
+ className: "text-xs text-text-muted",
23
+ children: [
24
+ "Program ",
25
+ e,
26
+ " is no longer readable."
27
+ ]
28
+ });
29
+ let r = n.data.context, a = f(r) ? r.lastAiAdjustment : null, o = f(a) && typeof a.status == "string" ? a.status : null, s = f(a) && typeof a.agentRunId == "string" ? a.agentRunId : null;
30
+ return /* @__PURE__ */ k("div", {
31
+ className: "flex flex-wrap items-center gap-2 text-xs text-text-secondary",
32
+ children: [
33
+ /* @__PURE__ */ O("span", {
34
+ className: "font-medium text-text-primary",
35
+ children: n.data.name
36
+ }),
37
+ /* @__PURE__ */ O(t, { status: n.data.status }),
38
+ o ? /* @__PURE__ */ k(D, { children: [
39
+ /* @__PURE__ */ O("span", { children: "·" }),
40
+ /* @__PURE__ */ O("span", { children: g[o] ?? o }),
41
+ s && /* @__PURE__ */ O("span", {
42
+ className: "font-mono text-text-muted",
43
+ children: s
44
+ })
45
+ ] }) : /* @__PURE__ */ O("span", {
46
+ className: "text-text-muted",
47
+ children: "· no AI adjustment recorded on this program"
48
+ })
49
+ ]
50
+ });
51
+ }
52
+ function N({ run: e, knownProgramId: t, onCancel: n, onSuccess: i }) {
53
+ let o = r(), u = a({ pagination: { limit: 100 } }), [d, f] = x(t ?? ""), [p, m] = x("MAINTAIN"), [h, g] = x(""), [b, S] = x(null);
54
+ return /* @__PURE__ */ k("form", {
55
+ onSubmit: (t) => {
56
+ if (t.preventDefault(), S(null), !d) {
57
+ S("Choose the program this decision concerns.");
58
+ return;
59
+ }
60
+ if (!h.trim()) {
61
+ S("A note is required — it is the record of why you decided this.");
62
+ return;
63
+ }
64
+ o.mutate({
65
+ runId: e.id,
66
+ programId: d,
67
+ assessment: p,
68
+ note: h.trim()
69
+ }, { onSuccess: () => {
70
+ g(""), i();
71
+ } });
72
+ },
73
+ className: "mt-4 space-y-4 border-t border-border-seam pt-4",
74
+ children: [
75
+ /* @__PURE__ */ O("p", {
76
+ className: "text-xs text-text-secondary",
77
+ children: "Your decision is appended to the ledger as a new run that supersedes this one — the original is never edited. Filing the same call the AI made records it as accepted; a different one records it as overridden."
78
+ }),
79
+ t ? /* @__PURE__ */ O(s, {
80
+ label: "Program",
81
+ hint: "Taken from this run's provenance.",
82
+ children: /* @__PURE__ */ O("input", {
83
+ className: c,
84
+ value: t,
85
+ readOnly: !0,
86
+ "aria-label": "Program this decision concerns"
87
+ })
88
+ }) : /* @__PURE__ */ O(s, {
89
+ label: "Program",
90
+ htmlFor: `override-program-${e.id}`,
91
+ required: !0,
92
+ hint: "This run predates its program, so pick the one it produced. A program the run never touched is rejected.",
93
+ children: /* @__PURE__ */ k("select", {
94
+ id: `override-program-${e.id}`,
95
+ className: c,
96
+ value: d,
97
+ onChange: (e) => f(e.target.value),
98
+ children: [/* @__PURE__ */ O("option", {
99
+ value: "",
100
+ children: "Select a program…"
101
+ }), (u.data?.items ?? []).map((e) => /* @__PURE__ */ O("option", {
102
+ value: e.id,
103
+ children: e.name
104
+ }, e.id))]
105
+ })
106
+ }),
107
+ /* @__PURE__ */ O(s, {
108
+ label: "Your assessment",
109
+ htmlFor: `override-assessment-${e.id}`,
110
+ required: !0,
111
+ hint: _[p],
112
+ children: /* @__PURE__ */ O("select", {
113
+ id: `override-assessment-${e.id}`,
114
+ className: c,
115
+ value: p,
116
+ onChange: (e) => m(e.target.value),
117
+ children: y.map((e) => /* @__PURE__ */ O("option", {
118
+ value: e,
119
+ children: v[e]
120
+ }, e))
121
+ })
122
+ }),
123
+ /* @__PURE__ */ O(s, {
124
+ label: "Note",
125
+ htmlFor: `override-note-${e.id}`,
126
+ required: !0,
127
+ children: /* @__PURE__ */ O("textarea", {
128
+ id: `override-note-${e.id}`,
129
+ className: c,
130
+ rows: 3,
131
+ value: h,
132
+ maxLength: 1e3,
133
+ onChange: (e) => g(e.target.value),
134
+ placeholder: "Why this call — what you saw that the model did not."
135
+ })
136
+ }),
137
+ b && /* @__PURE__ */ O("p", {
138
+ className: "text-sm text-status-error-text",
139
+ children: b
140
+ }),
141
+ o.isError && /* @__PURE__ */ O(l, { error: o.error }),
142
+ /* @__PURE__ */ k("div", {
143
+ className: "flex items-center justify-end gap-2",
144
+ children: [/* @__PURE__ */ O("button", {
145
+ type: "button",
146
+ onClick: n,
147
+ className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
148
+ children: "Cancel"
149
+ }), /* @__PURE__ */ k("button", {
150
+ type: "submit",
151
+ disabled: o.isPending,
152
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-60",
153
+ children: [o.isPending ? /* @__PURE__ */ O(E, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ O(T, { className: "h-4 w-4" }), "File decision"]
154
+ })]
155
+ })
156
+ ]
157
+ });
158
+ }
159
+ function P({ run: r, isFocused: i = !1, className: a }) {
160
+ let [s, c] = x(!1), [l, f] = x(!1), _ = m(r.decision), y = h(r.inputRefs), E = p(r.inputRefs), D = u(_.confidence), P = d(_.recommendedWeeklyLoadChangePct), F = r.status === "FAILED", I = F || _.isFailure;
161
+ return /* @__PURE__ */ k(j, {
162
+ treatment: "insight",
163
+ className: e("p-5", i && "ring-2 ring-[var(--color-focus-ring)]", a),
164
+ children: [
165
+ /* @__PURE__ */ k("div", {
166
+ className: "flex flex-wrap items-start justify-between gap-3",
167
+ children: [/* @__PURE__ */ k("div", {
168
+ className: "min-w-0",
169
+ children: [/* @__PURE__ */ k("h3", {
170
+ className: e("flex items-center gap-2 text-base font-semibold", I ? "text-status-error-text" : "text-text-primary"),
171
+ children: [I && /* @__PURE__ */ O(S, {
172
+ className: "h-4 w-4 shrink-0",
173
+ "aria-hidden": "true"
174
+ }), F ? "Decision not reached" : _.title]
175
+ }), /* @__PURE__ */ O("p", {
176
+ className: "mt-1 text-sm text-text-secondary",
177
+ children: r.promptSummary
178
+ })]
179
+ }), /* @__PURE__ */ k("div", {
180
+ className: "flex shrink-0 flex-wrap items-center gap-2",
181
+ children: [_.assessment && /* @__PURE__ */ O(t, {
182
+ status: v[_.assessment],
183
+ variant: b[_.assessment]
184
+ }), _.status && /* @__PURE__ */ O(A, {
185
+ variant: "outline",
186
+ children: g[_.status] ?? _.status
187
+ })]
188
+ })]
189
+ }),
190
+ /* @__PURE__ */ k("p", {
191
+ className: "mt-2 text-xs text-text-muted",
192
+ title: n(r.createdAt),
193
+ children: [
194
+ r.provider,
195
+ "/",
196
+ r.model,
197
+ " · ",
198
+ o(r.createdAt),
199
+ " · run",
200
+ " ",
201
+ /* @__PURE__ */ O("code", {
202
+ className: "font-mono",
203
+ children: r.id
204
+ })
205
+ ]
206
+ }),
207
+ /* @__PURE__ */ O("div", {
208
+ className: "mt-4",
209
+ children: F ? /* @__PURE__ */ k("div", {
210
+ className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3",
211
+ children: [/* @__PURE__ */ O("p", {
212
+ className: "text-sm font-medium text-status-error-text",
213
+ children: "The provider chain could not answer, so no decision was produced."
214
+ }), r.error && /* @__PURE__ */ O("p", {
215
+ className: "mt-1.5 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-status-error-text",
216
+ children: r.error
217
+ })]
218
+ }) : _.kind === "parse-failure" ? /* @__PURE__ */ k("div", {
219
+ className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3",
220
+ children: [
221
+ /* @__PURE__ */ O("p", {
222
+ className: "text-sm font-medium text-status-error-text",
223
+ children: "The model replied, but the reply could not be used."
224
+ }),
225
+ /* @__PURE__ */ O("p", {
226
+ className: "mt-1.5 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-status-error-text",
227
+ children: _.parseError
228
+ }),
229
+ /* @__PURE__ */ O("p", {
230
+ className: "mt-1.5 text-xs text-text-secondary",
231
+ children: "Nothing was applied to any program. The row is kept so the failure is auditable."
232
+ })
233
+ ]
234
+ }) : _.kind === "none" ? /* @__PURE__ */ O("p", {
235
+ className: "text-sm text-text-muted",
236
+ children: "This run recorded no decision payload."
237
+ }) : /* @__PURE__ */ k("div", {
238
+ className: "space-y-3",
239
+ children: [
240
+ _.rationale && /* @__PURE__ */ O("p", {
241
+ className: "text-sm text-text-secondary",
242
+ children: _.rationale
243
+ }),
244
+ _.note && /* @__PURE__ */ k("p", {
245
+ className: "rounded-lg bg-bg-sunken p-3 text-sm text-text-secondary",
246
+ children: [/* @__PURE__ */ O("span", {
247
+ className: "font-medium text-text-primary",
248
+ children: "Coach note: "
249
+ }), _.note]
250
+ }),
251
+ (D || P) && /* @__PURE__ */ k("div", {
252
+ className: "flex flex-wrap gap-1.5",
253
+ children: [D && /* @__PURE__ */ k("span", {
254
+ className: "inline-flex items-center rounded-md border border-border-seam bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary",
255
+ children: ["Confidence ", D]
256
+ }), P && /* @__PURE__ */ k("span", {
257
+ className: "inline-flex items-center rounded-md border border-border-seam bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary",
258
+ children: ["Weekly load ", P]
259
+ })]
260
+ }),
261
+ _.flags.length > 0 && /* @__PURE__ */ O("div", {
262
+ className: "flex flex-wrap gap-1.5",
263
+ children: _.flags.map((e) => /* @__PURE__ */ O("span", {
264
+ className: "inline-flex items-center rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs font-medium text-status-warning-text",
265
+ children: e
266
+ }, e))
267
+ }),
268
+ _.extra.length > 0 && /* @__PURE__ */ O("dl", {
269
+ className: "grid grid-cols-1 gap-x-6 gap-y-1 text-xs sm:grid-cols-2",
270
+ children: _.extra.map((e) => /* @__PURE__ */ k("div", {
271
+ className: "flex gap-1.5",
272
+ children: [/* @__PURE__ */ k("dt", {
273
+ className: "shrink-0 font-medium text-text-primary",
274
+ children: [e.label, ":"]
275
+ }), /* @__PURE__ */ O("dd", {
276
+ className: "min-w-0 break-words text-text-secondary",
277
+ children: e.value
278
+ })]
279
+ }, e.key))
280
+ })
281
+ ]
282
+ })
283
+ }),
284
+ /* @__PURE__ */ k("div", {
285
+ className: "mt-4 border-t border-border-seam pt-3",
286
+ children: [
287
+ /* @__PURE__ */ k("h4", {
288
+ className: "flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-muted",
289
+ children: [/* @__PURE__ */ O(w, {
290
+ className: "h-3.5 w-3.5",
291
+ "aria-hidden": "true"
292
+ }), "Considered"]
293
+ }),
294
+ y.length === 0 ? /* @__PURE__ */ O("p", {
295
+ className: "mt-1.5 text-xs text-text-muted",
296
+ children: "This run recorded no input references."
297
+ }) : /* @__PURE__ */ O("dl", {
298
+ className: "mt-1.5 grid grid-cols-1 gap-x-6 gap-y-1 text-xs sm:grid-cols-2",
299
+ children: y.map((e) => /* @__PURE__ */ k("div", {
300
+ className: "flex gap-1.5",
301
+ children: [/* @__PURE__ */ k("dt", {
302
+ className: "shrink-0 font-medium text-text-primary",
303
+ children: [e.label, ":"]
304
+ }), /* @__PURE__ */ O("dd", {
305
+ className: "min-w-0 break-words text-text-secondary",
306
+ children: e.value
307
+ })]
308
+ }, e.key))
309
+ }),
310
+ E && /* @__PURE__ */ O("div", {
311
+ className: "mt-2",
312
+ children: /* @__PURE__ */ O(M, { programId: E })
313
+ })
314
+ ]
315
+ }),
316
+ /* @__PURE__ */ O("div", {
317
+ className: "mt-4",
318
+ children: l && !s ? /* @__PURE__ */ k("p", {
319
+ className: "inline-flex items-center gap-1.5 text-sm text-status-success-text",
320
+ children: [/* @__PURE__ */ O(C, { className: "h-4 w-4" }), " Your decision was recorded as a new ledger row."]
321
+ }) : s ? /* @__PURE__ */ O(N, {
322
+ run: r,
323
+ knownProgramId: E,
324
+ onCancel: () => c(!1),
325
+ onSuccess: () => {
326
+ c(!1), f(!0);
327
+ }
328
+ }) : /* @__PURE__ */ k("button", {
329
+ type: "button",
330
+ onClick: () => {
331
+ f(!1), c(!0);
332
+ },
333
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
334
+ children: [/* @__PURE__ */ O(T, { className: "h-4 w-4" }), " File a coach decision"]
335
+ })
336
+ })
337
+ ]
338
+ });
339
+ }
340
+ //#endregion
341
+ export { P as DecisionCard };
342
+
343
+ //# sourceMappingURL=DecisionCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionCard.js","names":[],"sources":["../../../../src/atheletebridge/components/ai/DecisionCard.tsx"],"sourcesContent":["/**\n * Decision card\n * @module atheletebridge/components/ai\n *\n * One AI decision, rendered from the ledger row it was written to: the\n * `decision` payload, the `inputRefs` provenance (the ids and aggregate stats\n * the model actually considered), and the coach's review action\n * (`athOverrideAgentRun`).\n *\n * Three rules:\n * - A run whose decision carries `parseError` renders as a FAILED decision.\n * The provider answered, the answer was unusable, and the card says so —\n * an empty card would read as a silent success.\n * - A FAILED run shows the recorded upstream error, not a blank space.\n * - Nothing in the payload is hidden: keys this build does not recognise are\n * still listed (see `utils/aiDecision`).\n */\n\nimport { useState } from 'react';\nimport { AlertTriangle, Check, FileSearch, Gavel, Loader2 } from 'lucide-react';\nimport { Badge, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { FormField, fieldInputClass } from '../form';\nimport { StatusBadge } from '../StatusBadge';\nimport {\n usePrograms,\n useProgramAiState,\n useOverrideAgentRun,\n} from '../../hooks/useAthleteBridgeApi';\nimport type { AthAgentRun, AthAiAssessment } from '../../types';\nimport { cn } from '../../utils/cn';\nimport { formatDate } from '../../utils/formatters';\nimport { timeAgo } from '../../utils/timeAgo';\nimport {\n formatConfidence,\n formatLoadChange,\n isRecord,\n programIdFromInputRefs,\n summarizeDecision,\n toProvenanceEntries,\n} from '../../utils/aiDecision';\nimport {\n ADJUSTMENT_STATUS_LABELS,\n ASSESSMENT_DESCRIPTIONS,\n ASSESSMENT_LABELS,\n ASSESSMENT_OPTIONS,\n ASSESSMENT_VARIANT,\n} from './assessment';\nimport { AiErrorNotice } from './AiErrorNotice';\n\ninterface DecisionCardProps {\n run: AthAgentRun;\n /** Highlighted because it is the run selected in the activity feed. */\n isFocused?: boolean;\n className?: string;\n}\n\n/** The program's CURRENT AI state, so the card shows where the proposal landed. */\nfunction ProgramAiState({ programId }: { programId: string }) {\n const program = useProgramAiState(programId);\n\n if (program.isLoading) {\n return (\n <p className=\"inline-flex items-center gap-1.5 text-xs text-text-muted\">\n <Loader2 className=\"h-3 w-3 animate-spin\" /> Loading program state…\n </p>\n );\n }\n if (program.isError || !program.data) {\n // NOT_FOUND here is legitimate — the program may have been archived since.\n return <p className=\"text-xs text-text-muted\">Program {programId} is no longer readable.</p>;\n }\n\n const context = program.data.context;\n const adjustment = isRecord(context) ? context.lastAiAdjustment : null;\n const status =\n isRecord(adjustment) && typeof adjustment.status === 'string' ? adjustment.status : null;\n const agentRunId =\n isRecord(adjustment) && typeof adjustment.agentRunId === 'string'\n ? adjustment.agentRunId\n : null;\n\n return (\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"font-medium text-text-primary\">{program.data.name}</span>\n <StatusBadge status={program.data.status} />\n {status ? (\n <>\n <span>·</span>\n <span>{ADJUSTMENT_STATUS_LABELS[status] ?? status}</span>\n {agentRunId && <span className=\"font-mono text-text-muted\">{agentRunId}</span>}\n </>\n ) : (\n <span className=\"text-text-muted\">· no AI adjustment recorded on this program</span>\n )}\n </div>\n );\n}\n\n/** Coach review — appended as a NEW ledger row, never an edit of the original. */\nfunction OverrideForm({\n run,\n knownProgramId,\n onCancel,\n onSuccess,\n}: {\n run: AthAgentRun;\n knownProgramId: string | null;\n onCancel: () => void;\n onSuccess: () => void;\n}) {\n const override = useOverrideAgentRun();\n // Only needed when the run itself does not name a program: `athGenerateProgram`\n // runs before its program exists, so the link is written the other way round\n // (onto the program's `context.agentRunId`) and the coach has to say which.\n const programs = usePrograms({ pagination: { limit: 100 } });\n\n const [programId, setProgramId] = useState(knownProgramId ?? '');\n const [assessment, setAssessment] = useState<AthAiAssessment>('MAINTAIN');\n const [note, setNote] = useState('');\n const [validationError, setValidationError] = useState<string | null>(null);\n\n const handleSubmit = (event: React.FormEvent) => {\n event.preventDefault();\n setValidationError(null);\n if (!programId) {\n setValidationError('Choose the program this decision concerns.');\n return;\n }\n if (!note.trim()) {\n setValidationError('A note is required — it is the record of why you decided this.');\n return;\n }\n override.mutate(\n { runId: run.id, programId, assessment, note: note.trim() },\n {\n onSuccess: () => {\n setNote('');\n onSuccess();\n },\n }\n );\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"mt-4 space-y-4 border-t border-border-seam pt-4\">\n <p className=\"text-xs text-text-secondary\">\n Your decision is appended to the ledger as a new run that supersedes this one — the original\n is never edited. Filing the same call the AI made records it as accepted; a different one\n records it as overridden.\n </p>\n\n {knownProgramId ? (\n <FormField label=\"Program\" hint=\"Taken from this run's provenance.\">\n <input\n className={fieldInputClass}\n value={knownProgramId}\n readOnly\n aria-label=\"Program this decision concerns\"\n />\n </FormField>\n ) : (\n <FormField\n label=\"Program\"\n htmlFor={`override-program-${run.id}`}\n required\n hint=\"This run predates its program, so pick the one it produced. A program the run never touched is rejected.\"\n >\n <select\n id={`override-program-${run.id}`}\n className={fieldInputClass}\n value={programId}\n onChange={(event) => setProgramId(event.target.value)}\n >\n <option value=\"\">Select a program…</option>\n {(programs.data?.items ?? []).map((program) => (\n <option key={program.id} value={program.id}>\n {program.name}\n </option>\n ))}\n </select>\n </FormField>\n )}\n\n <FormField\n label=\"Your assessment\"\n htmlFor={`override-assessment-${run.id}`}\n required\n hint={ASSESSMENT_DESCRIPTIONS[assessment]}\n >\n <select\n id={`override-assessment-${run.id}`}\n className={fieldInputClass}\n value={assessment}\n onChange={(event) => setAssessment(event.target.value as AthAiAssessment)}\n >\n {ASSESSMENT_OPTIONS.map((option) => (\n <option key={option} value={option}>\n {ASSESSMENT_LABELS[option]}\n </option>\n ))}\n </select>\n </FormField>\n\n <FormField label=\"Note\" htmlFor={`override-note-${run.id}`} required>\n <textarea\n id={`override-note-${run.id}`}\n className={fieldInputClass}\n rows={3}\n value={note}\n maxLength={1000}\n onChange={(event) => setNote(event.target.value)}\n placeholder=\"Why this call — what you saw that the model did not.\"\n />\n </FormField>\n\n {validationError && <p className=\"text-sm text-status-error-text\">{validationError}</p>}\n {override.isError && <AiErrorNotice error={override.error} />}\n\n <div className=\"flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={override.isPending}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-60\"\n >\n {override.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Gavel className=\"h-4 w-4\" />\n )}\n File decision\n </button>\n </div>\n </form>\n );\n}\n\nexport function DecisionCard({ run, isFocused = false, className }: DecisionCardProps) {\n const [overrideOpen, setOverrideOpen] = useState(false);\n const [overrideDone, setOverrideDone] = useState(false);\n\n const summary = summarizeDecision(run.decision);\n const provenance = toProvenanceEntries(run.inputRefs);\n const programId = programIdFromInputRefs(run.inputRefs);\n const confidence = formatConfidence(summary.confidence);\n const loadChange = formatLoadChange(summary.recommendedWeeklyLoadChangePct);\n const runFailed = run.status === 'FAILED';\n const readsAsFailure = runFailed || summary.isFailure;\n\n return (\n <GlassCard\n treatment=\"insight\"\n className={cn('p-5', isFocused && 'ring-2 ring-[var(--color-focus-ring)]', className)}\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <h3\n className={cn(\n 'flex items-center gap-2 text-base font-semibold',\n readsAsFailure ? 'text-status-error-text' : 'text-text-primary'\n )}\n >\n {readsAsFailure && <AlertTriangle className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />}\n {runFailed ? 'Decision not reached' : summary.title}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">{run.promptSummary}</p>\n </div>\n <div className=\"flex shrink-0 flex-wrap items-center gap-2\">\n {summary.assessment && (\n <StatusBadge\n status={ASSESSMENT_LABELS[summary.assessment]}\n variant={ASSESSMENT_VARIANT[summary.assessment]}\n />\n )}\n {summary.status && (\n <Badge variant=\"outline\">\n {ADJUSTMENT_STATUS_LABELS[summary.status] ?? summary.status}\n </Badge>\n )}\n </div>\n </div>\n\n <p className=\"mt-2 text-xs text-text-muted\" title={formatDate(run.createdAt)}>\n {run.provider}/{run.model} · {timeAgo(run.createdAt)} · run{' '}\n <code className=\"font-mono\">{run.id}</code>\n </p>\n\n {/* The decision itself */}\n <div className=\"mt-4\">\n {runFailed ? (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3\">\n <p className=\"text-sm font-medium text-status-error-text\">\n The provider chain could not answer, so no decision was produced.\n </p>\n {run.error && (\n <p className=\"mt-1.5 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-status-error-text\">\n {run.error}\n </p>\n )}\n </div>\n ) : summary.kind === 'parse-failure' ? (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3\">\n <p className=\"text-sm font-medium text-status-error-text\">\n The model replied, but the reply could not be used.\n </p>\n <p className=\"mt-1.5 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-status-error-text\">\n {summary.parseError}\n </p>\n <p className=\"mt-1.5 text-xs text-text-secondary\">\n Nothing was applied to any program. The row is kept so the failure is auditable.\n </p>\n </div>\n ) : summary.kind === 'none' ? (\n <p className=\"text-sm text-text-muted\">This run recorded no decision payload.</p>\n ) : (\n <div className=\"space-y-3\">\n {summary.rationale && (\n <p className=\"text-sm text-text-secondary\">{summary.rationale}</p>\n )}\n {summary.note && (\n <p className=\"rounded-lg bg-bg-sunken p-3 text-sm text-text-secondary\">\n <span className=\"font-medium text-text-primary\">Coach note: </span>\n {summary.note}\n </p>\n )}\n {(confidence || loadChange) && (\n <div className=\"flex flex-wrap gap-1.5\">\n {confidence && (\n <span className=\"inline-flex items-center rounded-md border border-border-seam bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary\">\n Confidence {confidence}\n </span>\n )}\n {loadChange && (\n <span className=\"inline-flex items-center rounded-md border border-border-seam bg-bg-sunken px-2 py-0.5 text-xs font-medium tabular-nums text-text-secondary\">\n Weekly load {loadChange}\n </span>\n )}\n </div>\n )}\n {summary.flags.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {summary.flags.map((flag) => (\n <span\n key={flag}\n className=\"inline-flex items-center rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs font-medium text-status-warning-text\"\n >\n {flag}\n </span>\n ))}\n </div>\n )}\n {summary.extra.length > 0 && (\n <dl className=\"grid grid-cols-1 gap-x-6 gap-y-1 text-xs sm:grid-cols-2\">\n {summary.extra.map((entry) => (\n <div key={entry.key} className=\"flex gap-1.5\">\n <dt className=\"shrink-0 font-medium text-text-primary\">{entry.label}:</dt>\n <dd className=\"min-w-0 break-words text-text-secondary\">{entry.value}</dd>\n </div>\n ))}\n </dl>\n )}\n </div>\n )}\n </div>\n\n {/* Provenance — what the model was actually given */}\n <div className=\"mt-4 border-t border-border-seam pt-3\">\n <h4 className=\"flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-text-muted\">\n <FileSearch className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Considered\n </h4>\n {provenance.length === 0 ? (\n <p className=\"mt-1.5 text-xs text-text-muted\">This run recorded no input references.</p>\n ) : (\n <dl className=\"mt-1.5 grid grid-cols-1 gap-x-6 gap-y-1 text-xs sm:grid-cols-2\">\n {provenance.map((entry) => (\n <div key={entry.key} className=\"flex gap-1.5\">\n <dt className=\"shrink-0 font-medium text-text-primary\">{entry.label}:</dt>\n <dd className=\"min-w-0 break-words text-text-secondary\">{entry.value}</dd>\n </div>\n ))}\n </dl>\n )}\n {programId && (\n <div className=\"mt-2\">\n <ProgramAiState programId={programId} />\n </div>\n )}\n </div>\n\n {/* Coach review */}\n <div className=\"mt-4\">\n {overrideDone && !overrideOpen ? (\n <p className=\"inline-flex items-center gap-1.5 text-sm text-status-success-text\">\n <Check className=\"h-4 w-4\" /> Your decision was recorded as a new ledger row.\n </p>\n ) : !overrideOpen ? (\n <button\n type=\"button\"\n onClick={() => {\n setOverrideDone(false);\n setOverrideOpen(true);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Gavel className=\"h-4 w-4\" /> File a coach decision\n </button>\n ) : (\n <OverrideForm\n run={run}\n knownProgramId={programId}\n onCancel={() => setOverrideOpen(false)}\n onSuccess={() => {\n setOverrideOpen(false);\n setOverrideDone(true);\n }}\n />\n )}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Run a decision
3
+ * @module atheletebridge/components/ai
4
+ *
5
+ * The two live model calls a coach can make from AI Operations:
6
+ *
7
+ * - `athGenerateProgram` — designs a multi-week plan and writes it into the
8
+ * domain as a DRAFT `AthProgram` (+ drills, + sessions for a named athlete).
9
+ * The coach reviews and publishes it through the normal program lifecycle.
10
+ * - `athAdjustPlanFromPerformance` — reads an athlete's recent workout logs and
11
+ * performance metrics and records a PROPOSED adjustment on a program. It
12
+ * changes no prescribed load; a coach resolves it from the decision card.
13
+ *
14
+ * Both write a ledger row whether they succeed or fail, and both surface
15
+ * `AI_PROVIDER_UNAVAILABLE` with the id of the FAILED row rather than a generic
16
+ * toast.
17
+ */
18
+ export declare function RunDecisionPanel({ className }: {
19
+ className?: string;
20
+ }): import("react").JSX.Element;
21
+ //# sourceMappingURL=RunDecisionPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunDecisionPanel.d.ts","sourceRoot":"","sources":["../../../../src/atheletebridge/components/ai/RunDecisionPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAqXH,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BASrE"}