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.
Files changed (219) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +93 -15
  3. package/apps/local-dashboard/dist/assets/index-DgY2KGP-.css +1 -0
  4. package/apps/local-dashboard/dist/assets/index-Dhgv5BQO.js +15 -0
  5. package/apps/local-dashboard/dist/assets/vendor-react-C5oyHiV1.js +11 -0
  6. package/apps/local-dashboard/dist/assets/{vendor-table-BIiI3YhS.js → vendor-table-Bc_bbKd8.js} +1 -1
  7. package/apps/local-dashboard/dist/assets/vendor-ui-B3BPIYy7.js +1 -0
  8. package/apps/local-dashboard/dist/index.html +5 -5
  9. package/cli/selftune/adapters/codex/install.ts +310 -78
  10. package/cli/selftune/adapters/opencode/install.ts +3 -4
  11. package/cli/selftune/alpha-upload/build-payloads.ts +3 -3
  12. package/cli/selftune/alpha-upload/stage-canonical.ts +17 -11
  13. package/cli/selftune/auto-update.ts +200 -8
  14. package/cli/selftune/canonical-export.ts +55 -25
  15. package/cli/selftune/command-surface.ts +397 -0
  16. package/cli/selftune/contribute/contribute.ts +64 -13
  17. package/cli/selftune/contribution-config.ts +57 -3
  18. package/cli/selftune/contribution-preferences.ts +117 -0
  19. package/cli/selftune/contribution-signals.ts +8 -4
  20. package/cli/selftune/contribution-staging.ts +13 -2
  21. package/cli/selftune/contributions.ts +55 -121
  22. package/cli/selftune/creator-contributions.ts +29 -10
  23. package/cli/selftune/cron/setup.ts +7 -3
  24. package/cli/selftune/dashboard-contract.ts +73 -0
  25. package/cli/selftune/dashboard-server.ts +168 -17
  26. package/cli/selftune/dashboard.ts +350 -17
  27. package/cli/selftune/eval/baseline.ts +21 -5
  28. package/cli/selftune/eval/execution-eval.ts +170 -0
  29. package/cli/selftune/eval/family-overlap.ts +2 -2
  30. package/cli/selftune/eval/hooks-to-evals.ts +228 -82
  31. package/cli/selftune/eval/import-skillsbench.ts +2 -2
  32. package/cli/selftune/eval/invocation-classifier.ts +56 -0
  33. package/cli/selftune/eval/synthetic-evals.ts +5 -3
  34. package/cli/selftune/eval/unit-test-cli.ts +7 -4
  35. package/cli/selftune/evolution/apply-proposal.ts +295 -0
  36. package/cli/selftune/evolution/engines/replay-engine.ts +79 -57
  37. package/cli/selftune/evolution/evolve-body.ts +100 -39
  38. package/cli/selftune/evolution/evolve.ts +244 -52
  39. package/cli/selftune/evolution/rollback.ts +0 -1
  40. package/cli/selftune/evolution/validate-body.ts +68 -42
  41. package/cli/selftune/evolution/validate-host-replay.ts +510 -60
  42. package/cli/selftune/evolution/validate-proposal.ts +11 -150
  43. package/cli/selftune/evolution/validate-routing.ts +43 -41
  44. package/cli/selftune/evolution/validation-contract.ts +91 -0
  45. package/cli/selftune/grading/auto-grade.ts +11 -7
  46. package/cli/selftune/grading/grade-session.ts +10 -16
  47. package/cli/selftune/index.ts +35 -10
  48. package/cli/selftune/ingestors/claude-replay.ts +15 -10
  49. package/cli/selftune/ingestors/codex-wrapper.ts +3 -3
  50. package/cli/selftune/ingestors/opencode-ingest.ts +2 -2
  51. package/cli/selftune/ingestors/pi-ingest.ts +3 -2
  52. package/cli/selftune/init.ts +27 -3
  53. package/cli/selftune/localdb/direct-write.ts +35 -1
  54. package/cli/selftune/localdb/queries/cron.ts +34 -0
  55. package/cli/selftune/localdb/queries/dashboard.ts +834 -0
  56. package/cli/selftune/localdb/queries/evolution.ts +158 -0
  57. package/cli/selftune/localdb/queries/execution.ts +133 -0
  58. package/cli/selftune/localdb/queries/json.ts +18 -0
  59. package/cli/selftune/localdb/queries/monitoring.ts +263 -0
  60. package/cli/selftune/localdb/queries/raw.ts +95 -0
  61. package/cli/selftune/localdb/queries/staging.ts +270 -0
  62. package/cli/selftune/localdb/queries/trust.ts +392 -0
  63. package/cli/selftune/localdb/queries.ts +60 -2288
  64. package/cli/selftune/localdb/schema.ts +21 -0
  65. package/cli/selftune/monitoring/watch.ts +96 -29
  66. package/cli/selftune/normalization.ts +3 -0
  67. package/cli/selftune/observability.ts +4 -2
  68. package/cli/selftune/orchestrate/cli.ts +161 -0
  69. package/cli/selftune/orchestrate/execute.ts +295 -0
  70. package/cli/selftune/orchestrate/finalize.ts +157 -0
  71. package/cli/selftune/orchestrate/locks.ts +40 -0
  72. package/cli/selftune/orchestrate/plan.ts +131 -0
  73. package/cli/selftune/orchestrate/post-run.ts +59 -0
  74. package/cli/selftune/orchestrate/prepare.ts +334 -0
  75. package/cli/selftune/orchestrate/report.ts +182 -0
  76. package/cli/selftune/orchestrate/runtime.ts +120 -0
  77. package/cli/selftune/orchestrate/signals.ts +48 -0
  78. package/cli/selftune/orchestrate.ts +150 -1173
  79. package/cli/selftune/repair/skill-usage.ts +5 -2
  80. package/cli/selftune/routes/overview.ts +5 -2
  81. package/cli/selftune/routes/skill-report.ts +15 -2
  82. package/cli/selftune/schedule.ts +5 -5
  83. package/cli/selftune/status.ts +39 -2
  84. package/cli/selftune/testing-readiness.ts +597 -0
  85. package/cli/selftune/types.ts +44 -4
  86. package/cli/selftune/uninstall.ts +2 -1
  87. package/cli/selftune/utils/canonical-log.ts +1 -9
  88. package/cli/selftune/utils/cli-error.ts +9 -0
  89. package/cli/selftune/utils/llm-call.ts +126 -6
  90. package/cli/selftune/utils/skill-discovery.ts +2 -0
  91. package/cli/selftune/workflows/proposals.ts +184 -0
  92. package/cli/selftune/workflows/skill-scaffold.ts +241 -0
  93. package/cli/selftune/workflows/workflows.ts +100 -26
  94. package/node_modules/@selftune/telemetry-contract/fixtures/complete-push.ts +1 -1
  95. package/node_modules/@selftune/telemetry-contract/fixtures/evidence-only-push.ts +1 -1
  96. package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
  97. package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +1 -1
  98. package/node_modules/@selftune/telemetry-contract/src/schemas.ts +41 -1
  99. package/node_modules/@selftune/telemetry-contract/src/types.ts +103 -2
  100. package/package.json +25 -9
  101. package/packages/dashboard-core/AGENTS.md +18 -0
  102. package/packages/dashboard-core/README.md +30 -0
  103. package/packages/dashboard-core/index.ts +3 -0
  104. package/packages/dashboard-core/package.json +39 -0
  105. package/packages/dashboard-core/src/chrome/DashboardChrome.tsx +74 -0
  106. package/packages/dashboard-core/src/chrome/DashboardHeader.tsx +200 -0
  107. package/packages/dashboard-core/src/chrome/DashboardSidebar.tsx +219 -0
  108. package/packages/dashboard-core/src/chrome/RuntimeBadge.tsx +46 -0
  109. package/packages/dashboard-core/src/chrome/index.ts +14 -0
  110. package/packages/dashboard-core/src/chrome/types.ts +81 -0
  111. package/packages/dashboard-core/src/chrome/utils.ts +23 -0
  112. package/packages/dashboard-core/src/gates/FeatureGate.tsx +11 -0
  113. package/packages/dashboard-core/src/gates/LockedRoute.tsx +29 -0
  114. package/packages/dashboard-core/src/gates/UpgradeCard.tsx +89 -0
  115. package/packages/dashboard-core/src/gates/index.ts +3 -0
  116. package/packages/dashboard-core/src/host/DashboardHostProvider.tsx +62 -0
  117. package/packages/dashboard-core/src/host/adapter.ts +47 -0
  118. package/packages/dashboard-core/src/host/capabilities.ts +55 -0
  119. package/packages/dashboard-core/src/host/index.ts +3 -0
  120. package/packages/dashboard-core/src/models/analytics.ts +39 -0
  121. package/packages/dashboard-core/src/models/index.ts +4 -0
  122. package/packages/dashboard-core/src/models/overview.ts +98 -0
  123. package/packages/dashboard-core/src/models/runtime.ts +7 -0
  124. package/packages/dashboard-core/src/models/skills.ts +34 -0
  125. package/packages/dashboard-core/src/routes/index.ts +2 -0
  126. package/packages/dashboard-core/src/routes/manifest.test.ts +70 -0
  127. package/packages/dashboard-core/src/routes/manifest.ts +451 -0
  128. package/packages/dashboard-core/src/routes/types.ts +39 -0
  129. package/packages/dashboard-core/src/screens/analytics/AnalyticsScreen.tsx +278 -0
  130. package/packages/dashboard-core/src/screens/analytics/index.ts +1 -0
  131. package/packages/dashboard-core/src/screens/index.ts +37 -0
  132. package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.test.ts +101 -0
  133. package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.tsx +393 -0
  134. package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.test.tsx +113 -0
  135. package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.tsx +72 -0
  136. package/packages/dashboard-core/src/screens/overview/OverviewCoreSurface.tsx +71 -0
  137. package/packages/dashboard-core/src/screens/overview/OverviewOnboardingBanner.tsx +90 -0
  138. package/packages/dashboard-core/src/screens/overview/OverviewRunSummary.tsx +40 -0
  139. package/packages/dashboard-core/src/screens/overview/index.ts +16 -0
  140. package/packages/dashboard-core/src/screens/overview/types.ts +13 -0
  141. package/packages/dashboard-core/src/screens/skill-report/SkillReportDailyBreakdownSection.tsx +99 -0
  142. package/packages/dashboard-core/src/screens/skill-report/SkillReportDataQualityTabContent.tsx +35 -0
  143. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceRail.tsx +71 -0
  144. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceSection.tsx +63 -0
  145. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceTabContent.tsx +25 -0
  146. package/packages/dashboard-core/src/screens/skill-report/SkillReportInvocationsSection.tsx +24 -0
  147. package/packages/dashboard-core/src/screens/skill-report/SkillReportMissedQueriesSection.tsx +79 -0
  148. package/packages/dashboard-core/src/screens/skill-report/SkillReportScaffold.tsx +150 -0
  149. package/packages/dashboard-core/src/screens/skill-report/SkillReportSections.test.tsx +224 -0
  150. package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.test.tsx +76 -0
  151. package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.tsx +88 -0
  152. package/packages/dashboard-core/src/screens/skill-report/SkillReportTrendSection.tsx +33 -0
  153. package/packages/dashboard-core/src/screens/skill-report/SkillReportTrustBadge.tsx +67 -0
  154. package/packages/dashboard-core/src/screens/skill-report/index.ts +45 -0
  155. package/packages/dashboard-core/src/screens/skills/SkillsLibraryScreen.tsx +162 -0
  156. package/packages/dashboard-core/src/screens/skills/index.ts +6 -0
  157. package/packages/telemetry-contract/fixtures/complete-push.ts +1 -1
  158. package/packages/telemetry-contract/fixtures/evidence-only-push.ts +1 -1
  159. package/packages/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
  160. package/packages/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +1 -1
  161. package/packages/telemetry-contract/src/schemas.ts +41 -1
  162. package/packages/telemetry-contract/src/types.ts +103 -2
  163. package/packages/ui/src/components/EvidenceViewer.tsx +80 -25
  164. package/packages/ui/src/components/OverviewPanels.tsx +67 -26
  165. package/packages/ui/src/primitives/tabs.tsx +7 -6
  166. package/packages/ui/src/types.ts +10 -0
  167. package/skill/SKILL.md +130 -332
  168. package/skill/agents/diagnosis-analyst.md +3 -3
  169. package/skill/agents/evolution-reviewer.md +3 -3
  170. package/skill/agents/integration-guide.md +3 -3
  171. package/skill/agents/pattern-analyst.md +2 -2
  172. package/skill/references/cli-quick-reference.md +89 -0
  173. package/skill/references/creator-playbook.md +131 -0
  174. package/skill/references/examples.md +48 -0
  175. package/skill/references/troubleshooting.md +47 -0
  176. package/skill/references/version-history.md +1 -1
  177. package/skill/selftune.contribute.json +11 -0
  178. package/skill/{Workflows → workflows}/Baseline.md +20 -1
  179. package/skill/{Workflows → workflows}/Contribute.md +23 -10
  180. package/skill/{Workflows → workflows}/Contributions.md +13 -5
  181. package/skill/workflows/CreateTestDeploy.md +170 -0
  182. package/skill/{Workflows → workflows}/CreatorContributions.md +18 -6
  183. package/skill/{Workflows → workflows}/Cron.md +1 -1
  184. package/skill/{Workflows → workflows}/Dashboard.md +20 -0
  185. package/skill/{Workflows → workflows}/Doctor.md +1 -1
  186. package/skill/{Workflows → workflows}/Evals.md +67 -2
  187. package/skill/{Workflows → workflows}/Evolve.md +119 -30
  188. package/skill/{Workflows → workflows}/EvolveBody.md +41 -1
  189. package/skill/{Workflows → workflows}/Grade.md +1 -1
  190. package/skill/{Workflows → workflows}/Initialize.md +8 -4
  191. package/skill/{Workflows → workflows}/Orchestrate.md +13 -3
  192. package/skill/{Workflows → workflows}/Schedule.md +3 -3
  193. package/skill/workflows/SignalsDashboard.md +87 -0
  194. package/skill/{Workflows → workflows}/UnitTest.md +19 -0
  195. package/skill/{Workflows → workflows}/Watch.md +42 -2
  196. package/skill/{Workflows → workflows}/Workflows.md +39 -2
  197. package/apps/local-dashboard/dist/assets/index-CwOtTrUS.css +0 -1
  198. package/apps/local-dashboard/dist/assets/index-f1HQpbeH.js +0 -59
  199. package/apps/local-dashboard/dist/assets/vendor-react-CKkiCskZ.js +0 -11
  200. package/apps/local-dashboard/dist/assets/vendor-ui-jVSaIZey.js +0 -12
  201. /package/skill/{Workflows → workflows}/AlphaUpload.md +0 -0
  202. /package/skill/{Workflows → workflows}/AutoActivation.md +0 -0
  203. /package/skill/{Workflows → workflows}/Badge.md +0 -0
  204. /package/skill/{Workflows → workflows}/Composability.md +0 -0
  205. /package/skill/{Workflows → workflows}/EvolutionMemory.md +0 -0
  206. /package/skill/{Workflows → workflows}/ExportCanonical.md +0 -0
  207. /package/skill/{Workflows → workflows}/Hook.md +0 -0
  208. /package/skill/{Workflows → workflows}/ImportSkillsBench.md +0 -0
  209. /package/skill/{Workflows → workflows}/Ingest.md +0 -0
  210. /package/skill/{Workflows → workflows}/PlatformHooks.md +0 -0
  211. /package/skill/{Workflows → workflows}/Quickstart.md +0 -0
  212. /package/skill/{Workflows → workflows}/Recover.md +0 -0
  213. /package/skill/{Workflows → workflows}/Registry.md +0 -0
  214. /package/skill/{Workflows → workflows}/RepairSkillUsage.md +0 -0
  215. /package/skill/{Workflows → workflows}/Replay.md +0 -0
  216. /package/skill/{Workflows → workflows}/Rollback.md +0 -0
  217. /package/skill/{Workflows → workflows}/Sync.md +0 -0
  218. /package/skill/{Workflows → workflows}/Telemetry.md +0 -0
  219. /package/skill/{Workflows → workflows}/Uninstall.md +0 -0
@@ -0,0 +1,89 @@
1
+ import { ArrowUpRightIcon, CheckIcon, LockIcon } from "lucide-react";
2
+
3
+ interface UpgradeAction {
4
+ href: string;
5
+ label: string;
6
+ }
7
+
8
+ interface UpgradeCardProps {
9
+ eyebrow: string;
10
+ title: string;
11
+ description: string;
12
+ highlights?: readonly string[];
13
+ primaryAction: UpgradeAction;
14
+ secondaryAction?: UpgradeAction;
15
+ note?: string;
16
+ }
17
+
18
+ export function UpgradeCard({
19
+ eyebrow,
20
+ title,
21
+ description,
22
+ highlights = [],
23
+ primaryAction,
24
+ secondaryAction,
25
+ note,
26
+ }: UpgradeCardProps) {
27
+ return (
28
+ <section className="overflow-hidden rounded-[28px] border border-primary/15 bg-[radial-gradient(circle_at_top_left,rgba(79,242,255,0.18),transparent_32%),linear-gradient(180deg,rgba(8,16,27,0.98),rgba(7,12,22,0.96))] shadow-[0_24px_80px_rgba(0,0,0,0.35)]">
29
+ <div className="grid gap-10 p-8 lg:grid-cols-[minmax(0,1.1fr)_minmax(300px,0.9fr)] lg:p-10">
30
+ <div className="space-y-6">
31
+ <div className="inline-flex items-center gap-2 rounded-full border border-primary/20 bg-primary/10 px-3 py-1 text-[10px] font-semibold uppercase tracking-[0.22em] text-primary">
32
+ <LockIcon className="size-3" />
33
+ <span>{eyebrow}</span>
34
+ </div>
35
+ <div className="space-y-4">
36
+ <h1 className="max-w-2xl font-headline text-3xl font-semibold tracking-tight text-foreground sm:text-4xl">
37
+ {title}
38
+ </h1>
39
+ <p className="max-w-2xl text-base leading-7 text-slate-300">{description}</p>
40
+ </div>
41
+
42
+ <div className="flex flex-wrap gap-3">
43
+ <a
44
+ href={primaryAction.href}
45
+ target="_blank"
46
+ rel="noreferrer"
47
+ className="inline-flex items-center gap-2 rounded-full bg-primary px-5 py-2.5 text-sm font-medium text-primary-foreground transition hover:bg-primary/90"
48
+ >
49
+ <span>{primaryAction.label}</span>
50
+ <ArrowUpRightIcon className="size-4" />
51
+ </a>
52
+ {secondaryAction ? (
53
+ <a
54
+ href={secondaryAction.href}
55
+ target="_blank"
56
+ rel="noreferrer"
57
+ className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-background/40 px-5 py-2.5 text-sm font-medium text-slate-200 transition hover:border-primary/30 hover:text-primary"
58
+ >
59
+ <span>{secondaryAction.label}</span>
60
+ <ArrowUpRightIcon className="size-4" />
61
+ </a>
62
+ ) : null}
63
+ </div>
64
+
65
+ {note ? <p className="text-sm text-slate-500">{note}</p> : null}
66
+ </div>
67
+
68
+ <div className="rounded-[24px] border border-white/8 bg-white/4 p-6 backdrop-blur-sm">
69
+ <div className="mb-4 text-[10px] font-semibold uppercase tracking-[0.22em] text-slate-500">
70
+ What unlocks
71
+ </div>
72
+ <div className="space-y-3">
73
+ {highlights.map((highlight) => (
74
+ <div
75
+ key={highlight}
76
+ className="flex items-start gap-3 rounded-2xl border border-white/6 bg-background/40 px-4 py-3"
77
+ >
78
+ <div className="mt-0.5 flex size-5 items-center justify-center rounded-full bg-primary/12 text-primary">
79
+ <CheckIcon className="size-3.5" />
80
+ </div>
81
+ <p className="text-sm leading-6 text-slate-200">{highlight}</p>
82
+ </div>
83
+ ))}
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </section>
88
+ );
89
+ }
@@ -0,0 +1,3 @@
1
+ export { FeatureGate } from "./FeatureGate";
2
+ export { LockedRoute } from "./LockedRoute";
3
+ export { UpgradeCard } from "./UpgradeCard";
@@ -0,0 +1,62 @@
1
+ import { createContext, useContext, useMemo, type ReactNode } from "react";
2
+
3
+ import type { DashboardHostAdapter } from "./adapter";
4
+ import type { Capabilities, DashboardFeatureKey } from "./capabilities";
5
+ import { canUseFeature } from "./capabilities";
6
+
7
+ export interface DashboardHostContextValue {
8
+ adapter: DashboardHostAdapter;
9
+ capabilities: Capabilities;
10
+ }
11
+
12
+ const DashboardHostContext = createContext<DashboardHostContextValue | null>(null);
13
+
14
+ interface DashboardHostProviderProps {
15
+ adapter: DashboardHostAdapter;
16
+ capabilities: Capabilities;
17
+ children: ReactNode;
18
+ }
19
+
20
+ export function DashboardHostProvider({
21
+ adapter,
22
+ capabilities,
23
+ children,
24
+ }: DashboardHostProviderProps) {
25
+ const value = useMemo(
26
+ () => ({
27
+ adapter,
28
+ capabilities,
29
+ }),
30
+ [adapter, capabilities],
31
+ );
32
+
33
+ return <DashboardHostContext.Provider value={value}>{children}</DashboardHostContext.Provider>;
34
+ }
35
+
36
+ export function useDashboardHost(): DashboardHostContextValue {
37
+ const context = useContext(DashboardHostContext);
38
+ if (!context) {
39
+ throw new Error("useDashboardHost must be used within a DashboardHostProvider");
40
+ }
41
+ return context;
42
+ }
43
+
44
+ export function useOptionalDashboardHost(): DashboardHostContextValue | null {
45
+ return useContext(DashboardHostContext);
46
+ }
47
+
48
+ export function useDashboardHostAdapter(): DashboardHostAdapter {
49
+ return useDashboardHost().adapter;
50
+ }
51
+
52
+ export function useOptionalDashboardHostAdapter(): DashboardHostAdapter | null {
53
+ return useOptionalDashboardHost()?.adapter ?? null;
54
+ }
55
+
56
+ export function useCapabilities(): Capabilities {
57
+ return useDashboardHost().capabilities;
58
+ }
59
+
60
+ export function useFeatureEnabled(feature: DashboardFeatureKey): boolean {
61
+ return canUseFeature(useCapabilities(), feature);
62
+ }
@@ -0,0 +1,47 @@
1
+ import type {
2
+ AnalyticsModel,
3
+ OverviewModel,
4
+ RuntimeHealthModel,
5
+ SkillsModel,
6
+ } from "../models/index";
7
+
8
+ export interface DashboardUser {
9
+ id?: string;
10
+ name: string;
11
+ email?: string;
12
+ subtitle?: string;
13
+ image?: string | null;
14
+ }
15
+
16
+ export interface DashboardSessionState {
17
+ status: "loading" | "authenticated" | "anonymous";
18
+ user?: DashboardUser;
19
+ }
20
+
21
+ export interface DashboardHostLinks {
22
+ upgrade: string;
23
+ billing?: string;
24
+ docs?: string;
25
+ cloudDashboard?: string;
26
+ }
27
+
28
+ export interface DashboardHostActions {
29
+ signOut?(): Promise<void>;
30
+ openUpgrade(): void;
31
+ getOverviewWatchlist?(): Promise<string[]>;
32
+ updateOverviewWatchlist?(skills: string[]): Promise<string[]>;
33
+ }
34
+
35
+ export interface DashboardApiClient {
36
+ fetchOverview(): Promise<OverviewModel>;
37
+ fetchSkills(): Promise<SkillsModel>;
38
+ fetchAnalytics(): Promise<AnalyticsModel>;
39
+ fetchRuntimeHealth?(): Promise<RuntimeHealthModel>;
40
+ }
41
+
42
+ export interface DashboardHostAdapter {
43
+ useSession(): DashboardSessionState;
44
+ api: DashboardApiClient;
45
+ links: DashboardHostLinks;
46
+ actions: DashboardHostActions;
47
+ }
@@ -0,0 +1,55 @@
1
+ export const FEATURE_KEYS = [
2
+ "analytics",
3
+ "registry",
4
+ "signals",
5
+ "proposals",
6
+ "billing",
7
+ "teamAdmin",
8
+ "runtimeStatus",
9
+ ] as const;
10
+
11
+ export const DISCOVERABLE_FEATURE_KEYS = ["registry", "signals", "proposals", "billing"] as const;
12
+
13
+ export type DashboardHostKind = "local" | "cloud";
14
+ export type DashboardPlan = "oss" | "pro" | "team";
15
+ export type DashboardFeatureKey = (typeof FEATURE_KEYS)[number];
16
+ export type DashboardDiscoverableFeatureKey = (typeof DISCOVERABLE_FEATURE_KEYS)[number];
17
+
18
+ export type DashboardFeatureFlags = Record<DashboardFeatureKey, boolean>;
19
+ export type DashboardDiscoverableFlags = Record<DashboardDiscoverableFeatureKey, boolean>;
20
+
21
+ export interface Capabilities {
22
+ host: DashboardHostKind;
23
+ plan: DashboardPlan;
24
+ features: DashboardFeatureFlags;
25
+ discoverable: DashboardDiscoverableFlags;
26
+ }
27
+
28
+ export function canUseFeature(capabilities: Capabilities, feature: DashboardFeatureKey): boolean {
29
+ return capabilities.features[feature];
30
+ }
31
+
32
+ export function canDiscoverFeature(
33
+ capabilities: Capabilities,
34
+ feature: DashboardDiscoverableFeatureKey,
35
+ ): boolean {
36
+ return capabilities.discoverable[feature] || capabilities.features[feature];
37
+ }
38
+
39
+ export function withCapabilityOverrides(
40
+ base: Capabilities,
41
+ overrides: Partial<Capabilities>,
42
+ ): Capabilities {
43
+ return {
44
+ host: overrides.host ?? base.host,
45
+ plan: overrides.plan ?? base.plan,
46
+ features: {
47
+ ...base.features,
48
+ ...overrides.features,
49
+ },
50
+ discoverable: {
51
+ ...base.discoverable,
52
+ ...overrides.discoverable,
53
+ },
54
+ };
55
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./adapter";
2
+ export * from "./capabilities";
3
+ export * from "./DashboardHostProvider";
@@ -0,0 +1,39 @@
1
+ export interface PassRateTrendPointModel {
2
+ date: string;
3
+ passRate: number | null;
4
+ checkVolume: number;
5
+ }
6
+
7
+ export interface SkillRankingModel {
8
+ skillName: string;
9
+ passRate: number;
10
+ totalChecks: number;
11
+ rank?: number;
12
+ }
13
+
14
+ export interface DailyActivityModel {
15
+ date: string;
16
+ checks: number;
17
+ }
18
+
19
+ export interface EvolutionImpactModel {
20
+ skillName: string;
21
+ passRateBefore: number;
22
+ passRateAfter: number;
23
+ improvement: number;
24
+ }
25
+
26
+ export interface AnalyticsSummaryModel {
27
+ activeSkills: number;
28
+ totalChecks30d: number;
29
+ totalEvolutions: number;
30
+ avgImprovement: number;
31
+ }
32
+
33
+ export interface AnalyticsModel {
34
+ summary: AnalyticsSummaryModel;
35
+ passRateTrend: PassRateTrendPointModel[];
36
+ skillRankings: SkillRankingModel[];
37
+ dailyActivity: DailyActivityModel[];
38
+ evolutionImpact: EvolutionImpactModel[];
39
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./analytics";
2
+ export * from "./overview";
3
+ export * from "./runtime";
4
+ export * from "./skills";
@@ -0,0 +1,98 @@
1
+ export type OverviewAutonomyLevel = "healthy" | "watching" | "needs_review" | "blocked";
2
+ export type OverviewSeverity = "critical" | "warning" | "info";
3
+ export type OverviewTrustBucket = "at_risk" | "improving" | "uncertain" | "stable";
4
+ export type OverviewDecisionKind =
5
+ | "proposal_created"
6
+ | "proposal_rejected"
7
+ | "validation_failed"
8
+ | "proposal_deployed"
9
+ | "rollback_triggered"
10
+ | "regression_found";
11
+
12
+ export interface OverviewSummaryModel {
13
+ totalSkills: number;
14
+ avgPassRate30d: number | null;
15
+ unmatchedCount30d: number;
16
+ sessionsCount30d: number;
17
+ pendingCount: number;
18
+ evidenceCount: number;
19
+ }
20
+
21
+ export interface OverviewAutonomyModel {
22
+ level: OverviewAutonomyLevel;
23
+ summary: string;
24
+ attentionRequired: number;
25
+ skillsObserved: number;
26
+ pendingReviews: number;
27
+ lastRunAt: string | null;
28
+ }
29
+
30
+ export interface OverviewWatchlistEntryModel {
31
+ skillName: string;
32
+ bucket: OverviewTrustBucket;
33
+ lastSeen: string | null;
34
+ passRate: number | null;
35
+ checks: number;
36
+ }
37
+
38
+ export interface OverviewAttentionItemModel {
39
+ skillName: string;
40
+ severity: OverviewSeverity;
41
+ title: string;
42
+ body: string;
43
+ }
44
+
45
+ export interface OverviewDecisionModel {
46
+ skillName: string;
47
+ kind: OverviewDecisionKind;
48
+ timestamp: string;
49
+ summary: string;
50
+ }
51
+
52
+ export interface OverviewActivityItemModel {
53
+ id: string;
54
+ type: "evolution" | "proposal" | "unmatched";
55
+ skillName?: string;
56
+ timestamp: string;
57
+ title: string;
58
+ summary: string;
59
+ }
60
+
61
+ export interface PipelineJobModel {
62
+ id: string;
63
+ label: string;
64
+ status: "healthy" | "warning" | "error" | "idle";
65
+ lastRunAt?: string | null;
66
+ nextRunAt?: string | null;
67
+ }
68
+
69
+ export interface OverviewSignalsSummaryModel {
70
+ signalCount: number;
71
+ skillCount: number;
72
+ }
73
+
74
+ export interface OverviewSkillCardModel {
75
+ id?: string;
76
+ name: string;
77
+ scope: string | null;
78
+ platforms: string[];
79
+ passRate: number | null;
80
+ checks: number;
81
+ status: "HEALTHY" | "WARNING" | "CRITICAL" | "UNKNOWN";
82
+ hasEvidence: boolean;
83
+ uniqueSessions: number;
84
+ lastSeen: string | null;
85
+ }
86
+
87
+ export interface OverviewModel {
88
+ version?: string;
89
+ summary: OverviewSummaryModel;
90
+ autonomy: OverviewAutonomyModel | null;
91
+ skillCards: OverviewSkillCardModel[];
92
+ watchlist: OverviewWatchlistEntryModel[];
93
+ attention: OverviewAttentionItemModel[];
94
+ decisions: OverviewDecisionModel[];
95
+ activity: OverviewActivityItemModel[];
96
+ jobs: PipelineJobModel[];
97
+ signals: OverviewSignalsSummaryModel | null;
98
+ }
@@ -0,0 +1,7 @@
1
+ export interface RuntimeHealthModel {
2
+ workspaceRoot: string;
3
+ gitSha: string;
4
+ dbPath: string;
5
+ processMode: string;
6
+ watcherMode: "wal" | "jsonl" | "none";
7
+ }
@@ -0,0 +1,34 @@
1
+ export type SkillHealthStatus = "HEALTHY" | "WARNING" | "CRITICAL" | "UNKNOWN";
2
+
3
+ export interface SkillListItemModel {
4
+ id?: string;
5
+ name: string;
6
+ platforms: string[];
7
+ status: SkillHealthStatus;
8
+ passRate: number | null;
9
+ totalChecks: number;
10
+ uniqueSessions: number;
11
+ evidenceCount?: number;
12
+ lastSeen: string | null;
13
+ }
14
+
15
+ export interface SkillTrendPointModel {
16
+ date: string;
17
+ passRate: number | null;
18
+ checks: number;
19
+ }
20
+
21
+ export interface SkillDetailModel {
22
+ id?: string;
23
+ name: string;
24
+ status: SkillHealthStatus;
25
+ passRate: number | null;
26
+ totalChecks: number;
27
+ uniqueSessions: number;
28
+ lastSeen: string | null;
29
+ trends: SkillTrendPointModel[];
30
+ }
31
+
32
+ export interface SkillsModel {
33
+ items: SkillListItemModel[];
34
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export * from "./manifest";
@@ -0,0 +1,70 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import type { Capabilities } from "../host/capabilities";
4
+ import { resolveDashboardRoutes } from "./manifest";
5
+
6
+ const LOCAL_CAPABILITIES: Capabilities = {
7
+ host: "local",
8
+ plan: "oss",
9
+ features: {
10
+ analytics: true,
11
+ registry: false,
12
+ signals: false,
13
+ proposals: false,
14
+ billing: false,
15
+ teamAdmin: false,
16
+ runtimeStatus: true,
17
+ },
18
+ discoverable: {
19
+ registry: true,
20
+ signals: true,
21
+ proposals: true,
22
+ billing: false,
23
+ },
24
+ };
25
+
26
+ const CLOUD_CAPABILITIES: Capabilities = {
27
+ host: "cloud",
28
+ plan: "team",
29
+ features: {
30
+ analytics: true,
31
+ registry: true,
32
+ signals: true,
33
+ proposals: true,
34
+ billing: true,
35
+ teamAdmin: false,
36
+ runtimeStatus: false,
37
+ },
38
+ discoverable: {
39
+ registry: true,
40
+ signals: true,
41
+ proposals: true,
42
+ billing: true,
43
+ },
44
+ };
45
+
46
+ describe("resolveDashboardRoutes", () => {
47
+ it("keeps signals, proposals, and registry as locked host-only cloud modules in local", () => {
48
+ const routes = resolveDashboardRoutes("local", LOCAL_CAPABILITIES);
49
+ const byId = new Map(routes.map((route) => [route.id, route]));
50
+
51
+ expect(byId.get("signals")?.access).toBe("locked");
52
+ expect(byId.get("proposals")?.access).toBe("locked");
53
+ expect(byId.get("registry")?.access).toBe("locked");
54
+ expect(byId.get("status")?.access).toBe("enabled");
55
+ expect(byId.has("unmatched")).toBe(false);
56
+ expect(byId.has("settings")).toBe(false);
57
+ });
58
+
59
+ it("keeps status local-only and enables the cloud coordination modules in cloud", () => {
60
+ const routes = resolveDashboardRoutes("cloud", CLOUD_CAPABILITIES);
61
+ const byId = new Map(routes.map((route) => [route.id, route]));
62
+
63
+ expect(byId.get("signals")?.access).toBe("enabled");
64
+ expect(byId.get("proposals")?.access).toBe("enabled");
65
+ expect(byId.get("registry")?.access).toBe("enabled");
66
+ expect(byId.get("unmatched")?.access).toBe("enabled");
67
+ expect(byId.get("settings")?.access).toBe("enabled");
68
+ expect(byId.has("status")).toBe(false);
69
+ });
70
+ });