selftune 0.2.23 → 0.2.25
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/CHANGELOG.md +6 -0
- package/README.md +93 -15
- package/apps/local-dashboard/dist/assets/index-DgY2KGP-.css +1 -0
- package/apps/local-dashboard/dist/assets/index-Dhgv5BQO.js +15 -0
- package/apps/local-dashboard/dist/assets/vendor-react-C5oyHiV1.js +11 -0
- package/apps/local-dashboard/dist/assets/{vendor-table-BIiI3YhS.js → vendor-table-Bc_bbKd8.js} +1 -1
- package/apps/local-dashboard/dist/assets/vendor-ui-B3BPIYy7.js +1 -0
- package/apps/local-dashboard/dist/index.html +5 -5
- package/cli/selftune/adapters/codex/install.ts +310 -78
- package/cli/selftune/adapters/opencode/install.ts +3 -4
- package/cli/selftune/alpha-upload/build-payloads.ts +3 -3
- package/cli/selftune/alpha-upload/stage-canonical.ts +17 -11
- package/cli/selftune/auto-update.ts +200 -8
- package/cli/selftune/canonical-export.ts +55 -25
- package/cli/selftune/command-surface.ts +397 -0
- package/cli/selftune/contribute/contribute.ts +64 -13
- package/cli/selftune/contribution-config.ts +57 -3
- package/cli/selftune/contribution-preferences.ts +117 -0
- package/cli/selftune/contribution-signals.ts +8 -4
- package/cli/selftune/contribution-staging.ts +13 -2
- package/cli/selftune/contributions.ts +55 -121
- package/cli/selftune/creator-contributions.ts +29 -10
- package/cli/selftune/cron/setup.ts +7 -3
- package/cli/selftune/dashboard-contract.ts +73 -0
- package/cli/selftune/dashboard-server.ts +168 -17
- package/cli/selftune/dashboard.ts +350 -17
- package/cli/selftune/eval/baseline.ts +21 -5
- package/cli/selftune/eval/execution-eval.ts +170 -0
- package/cli/selftune/eval/family-overlap.ts +2 -2
- package/cli/selftune/eval/hooks-to-evals.ts +228 -82
- package/cli/selftune/eval/import-skillsbench.ts +2 -2
- package/cli/selftune/eval/invocation-classifier.ts +56 -0
- package/cli/selftune/eval/synthetic-evals.ts +5 -3
- package/cli/selftune/eval/unit-test-cli.ts +7 -4
- package/cli/selftune/evolution/apply-proposal.ts +295 -0
- package/cli/selftune/evolution/engines/replay-engine.ts +79 -57
- package/cli/selftune/evolution/evolve-body.ts +100 -39
- package/cli/selftune/evolution/evolve.ts +244 -52
- package/cli/selftune/evolution/rollback.ts +0 -1
- package/cli/selftune/evolution/validate-body.ts +68 -42
- package/cli/selftune/evolution/validate-host-replay.ts +510 -60
- package/cli/selftune/evolution/validate-proposal.ts +11 -150
- package/cli/selftune/evolution/validate-routing.ts +43 -41
- package/cli/selftune/evolution/validation-contract.ts +91 -0
- package/cli/selftune/grading/auto-grade.ts +11 -7
- package/cli/selftune/grading/grade-session.ts +10 -16
- package/cli/selftune/index.ts +35 -10
- package/cli/selftune/ingestors/claude-replay.ts +15 -10
- package/cli/selftune/ingestors/codex-wrapper.ts +3 -3
- package/cli/selftune/ingestors/opencode-ingest.ts +2 -2
- package/cli/selftune/ingestors/pi-ingest.ts +3 -2
- package/cli/selftune/init.ts +27 -3
- package/cli/selftune/localdb/direct-write.ts +35 -1
- package/cli/selftune/localdb/queries/cron.ts +34 -0
- package/cli/selftune/localdb/queries/dashboard.ts +834 -0
- package/cli/selftune/localdb/queries/evolution.ts +158 -0
- package/cli/selftune/localdb/queries/execution.ts +133 -0
- package/cli/selftune/localdb/queries/json.ts +18 -0
- package/cli/selftune/localdb/queries/monitoring.ts +263 -0
- package/cli/selftune/localdb/queries/raw.ts +95 -0
- package/cli/selftune/localdb/queries/staging.ts +270 -0
- package/cli/selftune/localdb/queries/trust.ts +392 -0
- package/cli/selftune/localdb/queries.ts +60 -2288
- package/cli/selftune/localdb/schema.ts +21 -0
- package/cli/selftune/monitoring/watch.ts +96 -29
- package/cli/selftune/normalization.ts +3 -0
- package/cli/selftune/observability.ts +4 -2
- package/cli/selftune/orchestrate/cli.ts +161 -0
- package/cli/selftune/orchestrate/execute.ts +295 -0
- package/cli/selftune/orchestrate/finalize.ts +157 -0
- package/cli/selftune/orchestrate/locks.ts +40 -0
- package/cli/selftune/orchestrate/plan.ts +131 -0
- package/cli/selftune/orchestrate/post-run.ts +59 -0
- package/cli/selftune/orchestrate/prepare.ts +334 -0
- package/cli/selftune/orchestrate/report.ts +182 -0
- package/cli/selftune/orchestrate/runtime.ts +120 -0
- package/cli/selftune/orchestrate/signals.ts +48 -0
- package/cli/selftune/orchestrate.ts +150 -1173
- package/cli/selftune/repair/skill-usage.ts +5 -2
- package/cli/selftune/routes/overview.ts +5 -2
- package/cli/selftune/routes/skill-report.ts +15 -2
- package/cli/selftune/schedule.ts +5 -5
- package/cli/selftune/status.ts +39 -2
- package/cli/selftune/testing-readiness.ts +597 -0
- package/cli/selftune/types.ts +44 -4
- package/cli/selftune/uninstall.ts +2 -1
- package/cli/selftune/utils/canonical-log.ts +1 -9
- package/cli/selftune/utils/cli-error.ts +9 -0
- package/cli/selftune/utils/llm-call.ts +126 -6
- package/cli/selftune/utils/skill-discovery.ts +2 -0
- package/cli/selftune/workflows/proposals.ts +184 -0
- package/cli/selftune/workflows/skill-scaffold.ts +241 -0
- package/cli/selftune/workflows/workflows.ts +100 -26
- package/node_modules/@selftune/telemetry-contract/fixtures/complete-push.ts +1 -1
- package/node_modules/@selftune/telemetry-contract/fixtures/evidence-only-push.ts +1 -1
- package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
- package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +1 -1
- package/node_modules/@selftune/telemetry-contract/src/schemas.ts +41 -1
- package/node_modules/@selftune/telemetry-contract/src/types.ts +103 -2
- package/package.json +25 -9
- package/packages/dashboard-core/AGENTS.md +18 -0
- package/packages/dashboard-core/README.md +30 -0
- package/packages/dashboard-core/index.ts +3 -0
- package/packages/dashboard-core/package.json +39 -0
- package/packages/dashboard-core/src/chrome/DashboardChrome.tsx +74 -0
- package/packages/dashboard-core/src/chrome/DashboardHeader.tsx +200 -0
- package/packages/dashboard-core/src/chrome/DashboardSidebar.tsx +219 -0
- package/packages/dashboard-core/src/chrome/RuntimeBadge.tsx +46 -0
- package/packages/dashboard-core/src/chrome/index.ts +14 -0
- package/packages/dashboard-core/src/chrome/types.ts +81 -0
- package/packages/dashboard-core/src/chrome/utils.ts +23 -0
- package/packages/dashboard-core/src/gates/FeatureGate.tsx +11 -0
- package/packages/dashboard-core/src/gates/LockedRoute.tsx +29 -0
- package/packages/dashboard-core/src/gates/UpgradeCard.tsx +89 -0
- package/packages/dashboard-core/src/gates/index.ts +3 -0
- package/packages/dashboard-core/src/host/DashboardHostProvider.tsx +62 -0
- package/packages/dashboard-core/src/host/adapter.ts +47 -0
- package/packages/dashboard-core/src/host/capabilities.ts +55 -0
- package/packages/dashboard-core/src/host/index.ts +3 -0
- package/packages/dashboard-core/src/models/analytics.ts +39 -0
- package/packages/dashboard-core/src/models/index.ts +4 -0
- package/packages/dashboard-core/src/models/overview.ts +98 -0
- package/packages/dashboard-core/src/models/runtime.ts +7 -0
- package/packages/dashboard-core/src/models/skills.ts +34 -0
- package/packages/dashboard-core/src/routes/index.ts +2 -0
- package/packages/dashboard-core/src/routes/manifest.test.ts +70 -0
- package/packages/dashboard-core/src/routes/manifest.ts +451 -0
- package/packages/dashboard-core/src/routes/types.ts +39 -0
- package/packages/dashboard-core/src/screens/analytics/AnalyticsScreen.tsx +278 -0
- package/packages/dashboard-core/src/screens/analytics/index.ts +1 -0
- package/packages/dashboard-core/src/screens/index.ts +37 -0
- package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.test.ts +101 -0
- package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.tsx +393 -0
- package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.test.tsx +113 -0
- package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.tsx +72 -0
- package/packages/dashboard-core/src/screens/overview/OverviewCoreSurface.tsx +71 -0
- package/packages/dashboard-core/src/screens/overview/OverviewOnboardingBanner.tsx +90 -0
- package/packages/dashboard-core/src/screens/overview/OverviewRunSummary.tsx +40 -0
- package/packages/dashboard-core/src/screens/overview/index.ts +16 -0
- package/packages/dashboard-core/src/screens/overview/types.ts +13 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportDailyBreakdownSection.tsx +99 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportDataQualityTabContent.tsx +35 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceRail.tsx +71 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceSection.tsx +63 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceTabContent.tsx +25 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportInvocationsSection.tsx +24 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportMissedQueriesSection.tsx +79 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportScaffold.tsx +150 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportSections.test.tsx +224 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.test.tsx +76 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.tsx +88 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportTrendSection.tsx +33 -0
- package/packages/dashboard-core/src/screens/skill-report/SkillReportTrustBadge.tsx +67 -0
- package/packages/dashboard-core/src/screens/skill-report/index.ts +45 -0
- package/packages/dashboard-core/src/screens/skills/SkillsLibraryScreen.tsx +162 -0
- package/packages/dashboard-core/src/screens/skills/index.ts +6 -0
- package/packages/telemetry-contract/fixtures/complete-push.ts +1 -1
- package/packages/telemetry-contract/fixtures/evidence-only-push.ts +1 -1
- package/packages/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
- package/packages/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +1 -1
- package/packages/telemetry-contract/src/schemas.ts +41 -1
- package/packages/telemetry-contract/src/types.ts +103 -2
- package/packages/ui/src/components/EvidenceViewer.tsx +80 -25
- package/packages/ui/src/components/OverviewPanels.tsx +67 -26
- package/packages/ui/src/primitives/tabs.tsx +7 -6
- package/packages/ui/src/types.ts +10 -0
- package/skill/SKILL.md +130 -332
- package/skill/agents/diagnosis-analyst.md +3 -3
- package/skill/agents/evolution-reviewer.md +3 -3
- package/skill/agents/integration-guide.md +3 -3
- package/skill/agents/pattern-analyst.md +2 -2
- package/skill/references/cli-quick-reference.md +89 -0
- package/skill/references/creator-playbook.md +131 -0
- package/skill/references/examples.md +48 -0
- package/skill/references/troubleshooting.md +47 -0
- package/skill/references/version-history.md +1 -1
- package/skill/selftune.contribute.json +11 -0
- package/skill/{Workflows → workflows}/Baseline.md +20 -1
- package/skill/{Workflows → workflows}/Contribute.md +23 -10
- package/skill/{Workflows → workflows}/Contributions.md +13 -5
- package/skill/workflows/CreateTestDeploy.md +170 -0
- package/skill/{Workflows → workflows}/CreatorContributions.md +18 -6
- package/skill/{Workflows → workflows}/Cron.md +1 -1
- package/skill/{Workflows → workflows}/Dashboard.md +20 -0
- package/skill/{Workflows → workflows}/Doctor.md +1 -1
- package/skill/{Workflows → workflows}/Evals.md +67 -2
- package/skill/{Workflows → workflows}/Evolve.md +119 -30
- package/skill/{Workflows → workflows}/EvolveBody.md +41 -1
- package/skill/{Workflows → workflows}/Grade.md +1 -1
- package/skill/{Workflows → workflows}/Initialize.md +8 -4
- package/skill/{Workflows → workflows}/Orchestrate.md +13 -3
- package/skill/{Workflows → workflows}/Schedule.md +3 -3
- package/skill/workflows/SignalsDashboard.md +87 -0
- package/skill/{Workflows → workflows}/UnitTest.md +19 -0
- package/skill/{Workflows → workflows}/Watch.md +42 -2
- package/skill/{Workflows → workflows}/Workflows.md +39 -2
- package/apps/local-dashboard/dist/assets/index-CwOtTrUS.css +0 -1
- package/apps/local-dashboard/dist/assets/index-f1HQpbeH.js +0 -59
- package/apps/local-dashboard/dist/assets/vendor-react-CKkiCskZ.js +0 -11
- package/apps/local-dashboard/dist/assets/vendor-ui-jVSaIZey.js +0 -12
- /package/skill/{Workflows → workflows}/AlphaUpload.md +0 -0
- /package/skill/{Workflows → workflows}/AutoActivation.md +0 -0
- /package/skill/{Workflows → workflows}/Badge.md +0 -0
- /package/skill/{Workflows → workflows}/Composability.md +0 -0
- /package/skill/{Workflows → workflows}/EvolutionMemory.md +0 -0
- /package/skill/{Workflows → workflows}/ExportCanonical.md +0 -0
- /package/skill/{Workflows → workflows}/Hook.md +0 -0
- /package/skill/{Workflows → workflows}/ImportSkillsBench.md +0 -0
- /package/skill/{Workflows → workflows}/Ingest.md +0 -0
- /package/skill/{Workflows → workflows}/PlatformHooks.md +0 -0
- /package/skill/{Workflows → workflows}/Quickstart.md +0 -0
- /package/skill/{Workflows → workflows}/Recover.md +0 -0
- /package/skill/{Workflows → workflows}/Registry.md +0 -0
- /package/skill/{Workflows → workflows}/RepairSkillUsage.md +0 -0
- /package/skill/{Workflows → workflows}/Replay.md +0 -0
- /package/skill/{Workflows → workflows}/Rollback.md +0 -0
- /package/skill/{Workflows → workflows}/Sync.md +0 -0
- /package/skill/{Workflows → workflows}/Telemetry.md +0 -0
- /package/skill/{Workflows → workflows}/Uninstall.md +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
SkillReportGuideSheet,
|
|
8
|
+
SkillReportOnboardingBanner,
|
|
9
|
+
SkillReportTopRow,
|
|
10
|
+
SkillTrustNarrativePanel,
|
|
11
|
+
TrustSignalsGrid,
|
|
12
|
+
} from "@selftune/ui/components";
|
|
13
|
+
import { Button } from "@selftune/ui/primitives";
|
|
14
|
+
import type { TrustFields, TrustState } from "@selftune/ui/types";
|
|
15
|
+
|
|
16
|
+
export interface SkillReportNextAction {
|
|
17
|
+
icon: ReactNode;
|
|
18
|
+
text: string;
|
|
19
|
+
actionLabel: string;
|
|
20
|
+
variant: "default" | "secondary" | "destructive" | "outline";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SkillReportScaffoldProps {
|
|
24
|
+
backLink: ReactNode;
|
|
25
|
+
title: string;
|
|
26
|
+
statusBadge?: ReactNode;
|
|
27
|
+
toolbarMeta?: ReactNode;
|
|
28
|
+
summary?: ReactNode;
|
|
29
|
+
showOnboardingBanner?: boolean;
|
|
30
|
+
guideButtonLabel?: string;
|
|
31
|
+
nextAction: SkillReportNextAction;
|
|
32
|
+
trustState: TrustState;
|
|
33
|
+
coverage?: TrustFields["coverage"];
|
|
34
|
+
evidenceQuality?: TrustFields["evidence_quality"];
|
|
35
|
+
routingQuality?: TrustFields["routing_quality"];
|
|
36
|
+
evolutionState?: TrustFields["evolution_state"];
|
|
37
|
+
dataHygiene?: TrustFields["data_hygiene"];
|
|
38
|
+
fallbackChecks: number;
|
|
39
|
+
fallbackSessions: number;
|
|
40
|
+
fallbackEvidenceRows: number;
|
|
41
|
+
fallbackEvolutionRows: number;
|
|
42
|
+
fallbackLatestAction?: string;
|
|
43
|
+
nextActionText: string;
|
|
44
|
+
children?: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function SkillReportScaffold({
|
|
48
|
+
backLink,
|
|
49
|
+
title,
|
|
50
|
+
statusBadge,
|
|
51
|
+
toolbarMeta,
|
|
52
|
+
summary,
|
|
53
|
+
showOnboardingBanner = false,
|
|
54
|
+
guideButtonLabel = "How to read this page",
|
|
55
|
+
nextAction,
|
|
56
|
+
trustState,
|
|
57
|
+
coverage,
|
|
58
|
+
evidenceQuality,
|
|
59
|
+
routingQuality,
|
|
60
|
+
evolutionState,
|
|
61
|
+
dataHygiene,
|
|
62
|
+
fallbackChecks,
|
|
63
|
+
fallbackSessions,
|
|
64
|
+
fallbackEvidenceRows,
|
|
65
|
+
fallbackEvolutionRows,
|
|
66
|
+
fallbackLatestAction,
|
|
67
|
+
nextActionText,
|
|
68
|
+
children,
|
|
69
|
+
}: SkillReportScaffoldProps) {
|
|
70
|
+
const [isGuideOpen, setIsGuideOpen] = useState(false);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
<SkillReportGuideSheet open={isGuideOpen} onOpenChange={setIsGuideOpen} />
|
|
75
|
+
|
|
76
|
+
<div className="@container/main flex flex-1 flex-col gap-5 p-4 lg:px-6 lg:pb-6 lg:pt-0">
|
|
77
|
+
<div className="sticky top-0 z-30 space-y-2 border-b border-border/15 bg-background/95 py-2.5 backdrop-blur supports-[backdrop-filter]:bg-background/85">
|
|
78
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
79
|
+
{backLink}
|
|
80
|
+
<h1 className="shrink-0 font-headline text-base font-semibold tracking-tight lg:text-lg">
|
|
81
|
+
{title}
|
|
82
|
+
</h1>
|
|
83
|
+
{statusBadge}
|
|
84
|
+
<div className="ml-auto flex shrink-0 items-center gap-4">
|
|
85
|
+
<Button variant="outline" size="sm" onClick={() => setIsGuideOpen(true)}>
|
|
86
|
+
{guideButtonLabel}
|
|
87
|
+
</Button>
|
|
88
|
+
{toolbarMeta}
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
{summary ? (
|
|
93
|
+
<div className="space-y-1.5 text-sm leading-relaxed text-muted-foreground">
|
|
94
|
+
{summary}
|
|
95
|
+
</div>
|
|
96
|
+
) : null}
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
{showOnboardingBanner ? (
|
|
100
|
+
<SkillReportOnboardingBanner onOpenGuide={() => setIsGuideOpen(true)} />
|
|
101
|
+
) : null}
|
|
102
|
+
|
|
103
|
+
<div className="space-y-4">
|
|
104
|
+
<SkillReportTopRow
|
|
105
|
+
nextAction={nextAction}
|
|
106
|
+
latestDecision={
|
|
107
|
+
(evolutionState?.evolution_rows ?? fallbackEvolutionRows) > 0 &&
|
|
108
|
+
(evolutionState?.latest_action ?? fallbackLatestAction)
|
|
109
|
+
? {
|
|
110
|
+
action: evolutionState?.latest_action ?? fallbackLatestAction ?? "No data",
|
|
111
|
+
timestamp: evolutionState?.latest_timestamp ?? null,
|
|
112
|
+
evolutionCount: evolutionState?.evolution_rows ?? fallbackEvolutionRows,
|
|
113
|
+
}
|
|
114
|
+
: undefined
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
|
|
118
|
+
<SkillTrustNarrativePanel
|
|
119
|
+
trustState={trustState}
|
|
120
|
+
coverage={coverage}
|
|
121
|
+
evidenceQuality={evidenceQuality}
|
|
122
|
+
routingQuality={routingQuality}
|
|
123
|
+
evolutionState={evolutionState}
|
|
124
|
+
dataHygiene={dataHygiene}
|
|
125
|
+
fallbackChecks={fallbackChecks}
|
|
126
|
+
fallbackSessions={fallbackSessions}
|
|
127
|
+
nextActionText={nextActionText}
|
|
128
|
+
onOpenGuide={() => setIsGuideOpen(true)}
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
<TrustSignalsGrid
|
|
132
|
+
coverage={coverage}
|
|
133
|
+
evidenceQuality={evidenceQuality}
|
|
134
|
+
routingQuality={routingQuality}
|
|
135
|
+
evolutionState={evolutionState}
|
|
136
|
+
fallbackChecks={fallbackChecks}
|
|
137
|
+
fallbackSessions={fallbackSessions}
|
|
138
|
+
fallbackEvidenceRows={fallbackEvidenceRows}
|
|
139
|
+
fallbackEvolutionRows={fallbackEvolutionRows}
|
|
140
|
+
fallbackLatestAction={fallbackLatestAction}
|
|
141
|
+
/>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
{children ? (
|
|
145
|
+
<div className="space-y-4 border-t border-border/10 pt-4">{children}</div>
|
|
146
|
+
) : null}
|
|
147
|
+
</div>
|
|
148
|
+
</>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
vi.mock("@selftune/ui/components", () => ({
|
|
6
|
+
DataQualityPanel: ({
|
|
7
|
+
evidenceQuality,
|
|
8
|
+
dataHygiene,
|
|
9
|
+
}: {
|
|
10
|
+
evidenceQuality?: { prompt_link_rate: number };
|
|
11
|
+
dataHygiene?: { raw_checks: number };
|
|
12
|
+
}) => (
|
|
13
|
+
<div>
|
|
14
|
+
Data Quality
|
|
15
|
+
{evidenceQuality ? ` / prompt ${evidenceQuality.prompt_link_rate}` : ""}
|
|
16
|
+
{dataHygiene ? ` / rows ${dataHygiene.raw_checks}` : ""}
|
|
17
|
+
</div>
|
|
18
|
+
),
|
|
19
|
+
EvidenceViewer: ({ proposalId }: { proposalId: string }) => (
|
|
20
|
+
<div>Evidence Viewer {proposalId}</div>
|
|
21
|
+
),
|
|
22
|
+
InvocationsPanel: ({
|
|
23
|
+
invocations,
|
|
24
|
+
sessionMetadata,
|
|
25
|
+
}: {
|
|
26
|
+
invocations: Array<unknown>;
|
|
27
|
+
sessionMetadata?: Array<unknown>;
|
|
28
|
+
}) => (
|
|
29
|
+
<div>
|
|
30
|
+
Invocations {invocations.length}
|
|
31
|
+
{sessionMetadata ? ` / sessions ${sessionMetadata.length}` : ""}
|
|
32
|
+
</div>
|
|
33
|
+
),
|
|
34
|
+
PromptEvidencePanel: ({
|
|
35
|
+
examples,
|
|
36
|
+
}: {
|
|
37
|
+
examples: { good: Array<unknown>; missed: Array<unknown>; noisy: Array<unknown> };
|
|
38
|
+
}) => (
|
|
39
|
+
<div>
|
|
40
|
+
Prompt Evidence / good {examples.good.length} / missed {examples.missed.length} / noisy{" "}
|
|
41
|
+
{examples.noisy.length}
|
|
42
|
+
</div>
|
|
43
|
+
),
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
vi.mock("@selftune/ui/primitives", () => ({
|
|
47
|
+
Card: ({ children }: { children?: ReactNode }) => <section>{children}</section>,
|
|
48
|
+
CardContent: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
vi.mock("./SkillReportEvidenceRail", () => ({
|
|
52
|
+
SkillReportEvidenceRail: ({ activeProposal }: { activeProposal: string | null }) => (
|
|
53
|
+
<div>Evidence Rail {activeProposal ?? "none"}</div>
|
|
54
|
+
),
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
import { SkillReportEvidenceSection } from "./SkillReportEvidenceSection";
|
|
58
|
+
import { SkillReportEvidenceTabContent } from "./SkillReportEvidenceTabContent";
|
|
59
|
+
import { SkillReportInvocationsSection } from "./SkillReportInvocationsSection";
|
|
60
|
+
import { SkillReportDataQualityTabContent } from "./SkillReportDataQualityTabContent";
|
|
61
|
+
|
|
62
|
+
describe("Skill report shared sections", () => {
|
|
63
|
+
it("renders the shared evidence viewer layout", () => {
|
|
64
|
+
const html = renderToStaticMarkup(
|
|
65
|
+
<SkillReportEvidenceSection
|
|
66
|
+
evolution={[
|
|
67
|
+
{
|
|
68
|
+
proposal_id: "p1",
|
|
69
|
+
action: "validated",
|
|
70
|
+
timestamp: "2026-04-11T00:00:00Z",
|
|
71
|
+
details: "Validated",
|
|
72
|
+
},
|
|
73
|
+
]}
|
|
74
|
+
activeProposal="p1"
|
|
75
|
+
onSelect={() => {}}
|
|
76
|
+
evidence={[
|
|
77
|
+
{
|
|
78
|
+
proposal_id: "p1",
|
|
79
|
+
target: "description",
|
|
80
|
+
stage: "validated",
|
|
81
|
+
timestamp: "2026-04-11T00:00:00Z",
|
|
82
|
+
rationale: null,
|
|
83
|
+
confidence: null,
|
|
84
|
+
original_text: null,
|
|
85
|
+
proposed_text: null,
|
|
86
|
+
validation: null,
|
|
87
|
+
details: null,
|
|
88
|
+
eval_set: [],
|
|
89
|
+
},
|
|
90
|
+
]}
|
|
91
|
+
viewerProposalId="p1"
|
|
92
|
+
showViewer
|
|
93
|
+
/>,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(html).toContain("Evidence Rail p1");
|
|
97
|
+
expect(html).toContain("Evidence Viewer p1");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("renders the empty state when the viewer is disabled", () => {
|
|
101
|
+
const html = renderToStaticMarkup(
|
|
102
|
+
<SkillReportEvidenceSection
|
|
103
|
+
evolution={[]}
|
|
104
|
+
activeProposal={null}
|
|
105
|
+
onSelect={() => {}}
|
|
106
|
+
evidence={[]}
|
|
107
|
+
viewerProposalId=""
|
|
108
|
+
showViewer={false}
|
|
109
|
+
emptyState={<div>No shared evidence yet</div>}
|
|
110
|
+
/>,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(html).toContain("No shared evidence yet");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("renders the shared invocations wrapper", () => {
|
|
117
|
+
const html = renderToStaticMarkup(
|
|
118
|
+
<SkillReportInvocationsSection
|
|
119
|
+
invocations={[
|
|
120
|
+
{
|
|
121
|
+
timestamp: "2026-04-11T00:00:00Z",
|
|
122
|
+
session_id: "sess-1",
|
|
123
|
+
triggered: true,
|
|
124
|
+
query: "test query",
|
|
125
|
+
invocation_mode: "implicit",
|
|
126
|
+
confidence: 0.7,
|
|
127
|
+
tool_name: null,
|
|
128
|
+
agent_type: "main",
|
|
129
|
+
},
|
|
130
|
+
]}
|
|
131
|
+
sessionMetadata={[
|
|
132
|
+
{
|
|
133
|
+
session_id: "sess-1",
|
|
134
|
+
agent_cli: "codex",
|
|
135
|
+
},
|
|
136
|
+
]}
|
|
137
|
+
callout={<div>Operational invocations only</div>}
|
|
138
|
+
/>,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
expect(html).toContain("Operational invocations only");
|
|
142
|
+
expect(html).toContain("Invocations 1 / sessions 1");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("renders prompt evidence ahead of the shared evidence viewer", () => {
|
|
146
|
+
const html = renderToStaticMarkup(
|
|
147
|
+
<SkillReportEvidenceTabContent
|
|
148
|
+
examples={{
|
|
149
|
+
good: [
|
|
150
|
+
{
|
|
151
|
+
timestamp: "2026-04-12T00:00:00Z",
|
|
152
|
+
session_id: "sess-1",
|
|
153
|
+
query_text: "good query",
|
|
154
|
+
triggered: true,
|
|
155
|
+
confidence: 0.91,
|
|
156
|
+
invocation_mode: "explicit",
|
|
157
|
+
prompt_kind: null,
|
|
158
|
+
source: "codex",
|
|
159
|
+
platform: "codex",
|
|
160
|
+
workspace_path: null,
|
|
161
|
+
query_origin: "matched_prompt",
|
|
162
|
+
is_system_like: false,
|
|
163
|
+
observation_kind: "canonical",
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
missed: [],
|
|
167
|
+
noisy: [],
|
|
168
|
+
}}
|
|
169
|
+
evolution={[]}
|
|
170
|
+
activeProposal={null}
|
|
171
|
+
onSelect={() => {}}
|
|
172
|
+
evidence={[]}
|
|
173
|
+
viewerProposalId=""
|
|
174
|
+
showViewer={false}
|
|
175
|
+
emptyState={<div>No shared evidence yet</div>}
|
|
176
|
+
/>,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(html).toContain("Prompt Evidence / good 1 / missed 0 / noisy 0");
|
|
180
|
+
expect(html).toContain("No shared evidence yet");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("renders the data-quality panel when metrics are available", () => {
|
|
184
|
+
const html = renderToStaticMarkup(
|
|
185
|
+
<SkillReportDataQualityTabContent
|
|
186
|
+
evidenceQuality={{
|
|
187
|
+
prompt_link_rate: 0.85,
|
|
188
|
+
inline_query_rate: 0.6,
|
|
189
|
+
user_prompt_rate: 0.7,
|
|
190
|
+
meta_prompt_rate: 0.05,
|
|
191
|
+
internal_prompt_rate: 0.03,
|
|
192
|
+
no_prompt_rate: 0.22,
|
|
193
|
+
system_like_rate: 0.04,
|
|
194
|
+
invocation_mode_coverage: 1,
|
|
195
|
+
confidence_coverage: 0.9,
|
|
196
|
+
source_coverage: 1,
|
|
197
|
+
scope_coverage: 0.95,
|
|
198
|
+
}}
|
|
199
|
+
dataHygiene={{
|
|
200
|
+
naming_variants: [],
|
|
201
|
+
source_breakdown: [],
|
|
202
|
+
prompt_kind_breakdown: [],
|
|
203
|
+
observation_breakdown: [],
|
|
204
|
+
raw_checks: 42,
|
|
205
|
+
operational_checks: 40,
|
|
206
|
+
internal_prompt_rows: 1,
|
|
207
|
+
internal_prompt_rate: 0.02,
|
|
208
|
+
legacy_rows: 1,
|
|
209
|
+
legacy_rate: 0.02,
|
|
210
|
+
repaired_rows: 0,
|
|
211
|
+
repaired_rate: 0,
|
|
212
|
+
}}
|
|
213
|
+
/>,
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
expect(html).toContain("Data Quality / prompt 0.85 / rows 42");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("renders the empty data-quality state when metrics are unavailable", () => {
|
|
220
|
+
const html = renderToStaticMarkup(<SkillReportDataQualityTabContent />);
|
|
221
|
+
|
|
222
|
+
expect(html).toContain("Detailed data-quality metrics are not available for this skill yet.");
|
|
223
|
+
});
|
|
224
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
vi.mock("@selftune/ui/primitives", () => ({
|
|
6
|
+
Tabs: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
|
|
7
|
+
TabsList: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
|
|
8
|
+
TabsTrigger: ({ children }: { children?: ReactNode }) => <button>{children}</button>,
|
|
9
|
+
TabsContent: ({ children }: { children?: ReactNode }) => <section>{children}</section>,
|
|
10
|
+
Tooltip: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
|
|
11
|
+
TooltipTrigger: ({ children, render }: { children?: ReactNode; render?: ReactNode }) => (
|
|
12
|
+
<div>
|
|
13
|
+
{render}
|
|
14
|
+
{children}
|
|
15
|
+
</div>
|
|
16
|
+
),
|
|
17
|
+
TooltipContent: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
import { SkillReportTabs } from "./SkillReportTabs";
|
|
21
|
+
|
|
22
|
+
describe("SkillReportTabs", () => {
|
|
23
|
+
it("renders only visible tabs and their content", () => {
|
|
24
|
+
const html = renderToStaticMarkup(
|
|
25
|
+
<SkillReportTabs
|
|
26
|
+
defaultValue="evidence"
|
|
27
|
+
tabs={[
|
|
28
|
+
{
|
|
29
|
+
value: "evidence",
|
|
30
|
+
label: "Evidence",
|
|
31
|
+
content: <div>Evidence body</div>,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: "invocations",
|
|
35
|
+
label: "Invocations",
|
|
36
|
+
content: <div>Invocations body</div>,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
value: "hidden",
|
|
40
|
+
label: "Hidden",
|
|
41
|
+
hidden: true,
|
|
42
|
+
content: <div>Hidden body</div>,
|
|
43
|
+
},
|
|
44
|
+
]}
|
|
45
|
+
/>,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(html).toContain("Evidence");
|
|
49
|
+
expect(html).toContain("Invocations");
|
|
50
|
+
expect(html).toContain("Evidence body");
|
|
51
|
+
expect(html).toContain("Invocations body");
|
|
52
|
+
expect(html).not.toContain("Hidden");
|
|
53
|
+
expect(html).not.toContain("Hidden body");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("renders tooltip and badge content when configured", () => {
|
|
57
|
+
const html = renderToStaticMarkup(
|
|
58
|
+
<SkillReportTabs
|
|
59
|
+
defaultValue="invocations"
|
|
60
|
+
tabs={[
|
|
61
|
+
{
|
|
62
|
+
value: "invocations",
|
|
63
|
+
label: "Invocations",
|
|
64
|
+
badge: <span>12</span>,
|
|
65
|
+
tooltip: "Operational invocations only",
|
|
66
|
+
content: <div>Invocations body</div>,
|
|
67
|
+
},
|
|
68
|
+
]}
|
|
69
|
+
/>,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
expect(html).toContain("Invocations");
|
|
73
|
+
expect(html).toContain("12");
|
|
74
|
+
expect(html).toContain("Operational invocations only");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Tabs,
|
|
7
|
+
TabsContent,
|
|
8
|
+
TabsList,
|
|
9
|
+
TabsTrigger,
|
|
10
|
+
Tooltip,
|
|
11
|
+
TooltipContent,
|
|
12
|
+
TooltipTrigger,
|
|
13
|
+
} from "@selftune/ui/primitives";
|
|
14
|
+
|
|
15
|
+
export interface SkillReportTabDefinition {
|
|
16
|
+
value: string;
|
|
17
|
+
label: ReactNode;
|
|
18
|
+
badge?: ReactNode;
|
|
19
|
+
tooltip?: ReactNode;
|
|
20
|
+
content: ReactNode;
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
contentClassName?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SkillReportTabsProps {
|
|
26
|
+
tabs: SkillReportTabDefinition[];
|
|
27
|
+
value?: string;
|
|
28
|
+
defaultValue?: string;
|
|
29
|
+
onValueChange?: (value: string) => void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const TRIGGER_CLASS_NAME =
|
|
33
|
+
"rounded-lg px-3 font-headline text-xs uppercase tracking-wider data-active:bg-background/70 data-active:text-foreground";
|
|
34
|
+
|
|
35
|
+
export function SkillReportTabs({
|
|
36
|
+
tabs,
|
|
37
|
+
value,
|
|
38
|
+
defaultValue,
|
|
39
|
+
onValueChange,
|
|
40
|
+
}: SkillReportTabsProps) {
|
|
41
|
+
const visibleTabs = tabs.filter((tab) => !tab.hidden);
|
|
42
|
+
if (visibleTabs.length === 0) return null;
|
|
43
|
+
|
|
44
|
+
const firstValue = visibleTabs[0]?.value;
|
|
45
|
+
const tabsProps =
|
|
46
|
+
value !== undefined
|
|
47
|
+
? { value, onValueChange }
|
|
48
|
+
: { defaultValue: defaultValue ?? firstValue, onValueChange };
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Tabs {...tabsProps}>
|
|
52
|
+
<TabsList
|
|
53
|
+
variant="line"
|
|
54
|
+
className="rounded-xl border border-border/10 bg-muted/20 px-1.5 py-1"
|
|
55
|
+
>
|
|
56
|
+
{visibleTabs.map((tab) => {
|
|
57
|
+
const triggerChildren = (
|
|
58
|
+
<>
|
|
59
|
+
{tab.label}
|
|
60
|
+
{tab.badge}
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return tab.tooltip ? (
|
|
65
|
+
<Tooltip key={tab.value}>
|
|
66
|
+
<TooltipTrigger
|
|
67
|
+
render={<TabsTrigger value={tab.value} className={TRIGGER_CLASS_NAME} />}
|
|
68
|
+
>
|
|
69
|
+
{triggerChildren}
|
|
70
|
+
</TooltipTrigger>
|
|
71
|
+
<TooltipContent>{tab.tooltip}</TooltipContent>
|
|
72
|
+
</Tooltip>
|
|
73
|
+
) : (
|
|
74
|
+
<TabsTrigger key={tab.value} value={tab.value} className={TRIGGER_CLASS_NAME}>
|
|
75
|
+
{triggerChildren}
|
|
76
|
+
</TabsTrigger>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</TabsList>
|
|
80
|
+
|
|
81
|
+
{visibleTabs.map((tab) => (
|
|
82
|
+
<TabsContent key={tab.value} value={tab.value} className={tab.contentClassName}>
|
|
83
|
+
{tab.content}
|
|
84
|
+
</TabsContent>
|
|
85
|
+
))}
|
|
86
|
+
</Tabs>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
import { PassRateTrendChart, type PassRateTrendPoint } from "@selftune/ui/components";
|
|
6
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@selftune/ui/primitives";
|
|
7
|
+
|
|
8
|
+
export interface SkillReportTrendSectionProps {
|
|
9
|
+
data: PassRateTrendPoint[];
|
|
10
|
+
title?: ReactNode;
|
|
11
|
+
mode?: "pass_rate" | "volume";
|
|
12
|
+
isLoading?: boolean;
|
|
13
|
+
loadingState?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function SkillReportTrendSection({
|
|
17
|
+
data,
|
|
18
|
+
title = "Pass Rate Trend",
|
|
19
|
+
mode = "pass_rate",
|
|
20
|
+
isLoading = false,
|
|
21
|
+
loadingState,
|
|
22
|
+
}: SkillReportTrendSectionProps) {
|
|
23
|
+
return (
|
|
24
|
+
<Card className="bg-muted border-none shadow-none ring-0">
|
|
25
|
+
<CardHeader>
|
|
26
|
+
<CardTitle className="font-headline text-lg tracking-tight">{title}</CardTitle>
|
|
27
|
+
</CardHeader>
|
|
28
|
+
<CardContent>
|
|
29
|
+
{isLoading && loadingState ? loadingState : <PassRateTrendChart data={data} mode={mode} />}
|
|
30
|
+
</CardContent>
|
|
31
|
+
</Card>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
EyeIcon,
|
|
4
|
+
ShieldAlertIcon,
|
|
5
|
+
ShieldCheckIcon,
|
|
6
|
+
ShieldIcon,
|
|
7
|
+
ShieldQuestionIcon,
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
|
|
10
|
+
import { Badge } from "@selftune/ui/primitives";
|
|
11
|
+
import type { TrustState } from "@selftune/ui/types";
|
|
12
|
+
|
|
13
|
+
export function SkillReportTrustBadge({ state }: { state: TrustState }) {
|
|
14
|
+
const config = getSkillReportTrustBadgeConfig(state);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Badge variant={config.variant} className="gap-1 shrink-0 text-[10px]">
|
|
18
|
+
{config.icon}
|
|
19
|
+
{config.label}
|
|
20
|
+
</Badge>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getSkillReportTrustBadgeConfig(state: TrustState): {
|
|
25
|
+
label: string;
|
|
26
|
+
variant: "default" | "secondary" | "destructive" | "outline";
|
|
27
|
+
icon: ReactNode;
|
|
28
|
+
} {
|
|
29
|
+
switch (state) {
|
|
30
|
+
case "low_sample":
|
|
31
|
+
return {
|
|
32
|
+
label: "Low Sample",
|
|
33
|
+
variant: "secondary",
|
|
34
|
+
icon: <ShieldQuestionIcon className="size-3" />,
|
|
35
|
+
};
|
|
36
|
+
case "observed":
|
|
37
|
+
return {
|
|
38
|
+
label: "Observed",
|
|
39
|
+
variant: "outline",
|
|
40
|
+
icon: <EyeIcon className="size-3" />,
|
|
41
|
+
};
|
|
42
|
+
case "watch":
|
|
43
|
+
return {
|
|
44
|
+
label: "Watch",
|
|
45
|
+
variant: "secondary",
|
|
46
|
+
icon: <ShieldAlertIcon className="size-3" />,
|
|
47
|
+
};
|
|
48
|
+
case "validated":
|
|
49
|
+
return {
|
|
50
|
+
label: "Validated",
|
|
51
|
+
variant: "default",
|
|
52
|
+
icon: <ShieldCheckIcon className="size-3" />,
|
|
53
|
+
};
|
|
54
|
+
case "deployed":
|
|
55
|
+
return {
|
|
56
|
+
label: "Deployed",
|
|
57
|
+
variant: "default",
|
|
58
|
+
icon: <ShieldCheckIcon className="size-3" />,
|
|
59
|
+
};
|
|
60
|
+
case "rolled_back":
|
|
61
|
+
return {
|
|
62
|
+
label: "Rolled Back",
|
|
63
|
+
variant: "destructive",
|
|
64
|
+
icon: <ShieldIcon className="size-3" />,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SkillReportEvidenceSection,
|
|
3
|
+
type SkillReportEvidenceSectionProps,
|
|
4
|
+
} from "./SkillReportEvidenceSection";
|
|
5
|
+
export {
|
|
6
|
+
SkillReportEvidenceRail,
|
|
7
|
+
type SkillReportEvidenceRailProps,
|
|
8
|
+
} from "./SkillReportEvidenceRail";
|
|
9
|
+
export {
|
|
10
|
+
SkillReportInvocationsSection,
|
|
11
|
+
type SkillReportInvocationsSectionProps,
|
|
12
|
+
} from "./SkillReportInvocationsSection";
|
|
13
|
+
export {
|
|
14
|
+
SkillReportEvidenceTabContent,
|
|
15
|
+
type SkillReportEvidenceTabContentProps,
|
|
16
|
+
} from "./SkillReportEvidenceTabContent";
|
|
17
|
+
export {
|
|
18
|
+
SkillReportDataQualityTabContent,
|
|
19
|
+
type SkillReportDataQualityTabContentProps,
|
|
20
|
+
} from "./SkillReportDataQualityTabContent";
|
|
21
|
+
export {
|
|
22
|
+
SkillReportTrendSection,
|
|
23
|
+
type SkillReportTrendSectionProps,
|
|
24
|
+
} from "./SkillReportTrendSection";
|
|
25
|
+
export {
|
|
26
|
+
SkillReportDailyBreakdownSection,
|
|
27
|
+
type SkillReportDailyBreakdownRow,
|
|
28
|
+
type SkillReportDailyBreakdownSectionProps,
|
|
29
|
+
} from "./SkillReportDailyBreakdownSection";
|
|
30
|
+
export {
|
|
31
|
+
SkillReportMissedQueriesSection,
|
|
32
|
+
type SkillReportMissedQueryRow,
|
|
33
|
+
type SkillReportMissedQueriesSectionProps,
|
|
34
|
+
} from "./SkillReportMissedQueriesSection";
|
|
35
|
+
export {
|
|
36
|
+
SkillReportTabs,
|
|
37
|
+
type SkillReportTabDefinition,
|
|
38
|
+
type SkillReportTabsProps,
|
|
39
|
+
} from "./SkillReportTabs";
|
|
40
|
+
export {
|
|
41
|
+
SkillReportScaffold,
|
|
42
|
+
type SkillReportNextAction,
|
|
43
|
+
type SkillReportScaffoldProps,
|
|
44
|
+
} from "./SkillReportScaffold";
|
|
45
|
+
export { SkillReportTrustBadge, getSkillReportTrustBadgeConfig } from "./SkillReportTrustBadge";
|