selftune 0.2.22 → 0.2.24

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 (270) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +95 -15
  3. package/apps/local-dashboard/dist/assets/index-DgY2KGP-.css +1 -0
  4. package/apps/local-dashboard/dist/assets/index-Dmx7LPVX.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/adapters/pi/hook.ts +273 -0
  12. package/cli/selftune/adapters/pi/install.ts +207 -0
  13. package/cli/selftune/alpha-upload/build-payloads.ts +3 -3
  14. package/cli/selftune/alpha-upload/stage-canonical.ts +17 -11
  15. package/cli/selftune/auto-update.ts +200 -8
  16. package/cli/selftune/canonical-export.ts +55 -25
  17. package/cli/selftune/command-surface.ts +397 -0
  18. package/cli/selftune/constants.ts +10 -1
  19. package/cli/selftune/contribute/contribute.ts +64 -13
  20. package/cli/selftune/contribution-config.ts +57 -3
  21. package/cli/selftune/contribution-preferences.ts +117 -0
  22. package/cli/selftune/contribution-signals.ts +8 -4
  23. package/cli/selftune/contribution-staging.ts +13 -2
  24. package/cli/selftune/contributions.ts +55 -121
  25. package/cli/selftune/creator-contributions.ts +29 -10
  26. package/cli/selftune/cron/setup.ts +7 -3
  27. package/cli/selftune/dashboard-contract.ts +87 -0
  28. package/cli/selftune/dashboard-server.ts +168 -17
  29. package/cli/selftune/dashboard.ts +350 -17
  30. package/cli/selftune/eval/baseline.ts +21 -5
  31. package/cli/selftune/eval/execution-eval.ts +170 -0
  32. package/cli/selftune/eval/family-overlap.ts +2 -2
  33. package/cli/selftune/eval/hooks-to-evals.ts +228 -82
  34. package/cli/selftune/eval/import-skillsbench.ts +2 -2
  35. package/cli/selftune/eval/invocation-classifier.ts +56 -0
  36. package/cli/selftune/eval/synthetic-evals.ts +5 -3
  37. package/cli/selftune/eval/unit-test-cli.ts +7 -4
  38. package/cli/selftune/evolution/apply-proposal.ts +295 -0
  39. package/cli/selftune/evolution/engines/judge-engine.ts +96 -0
  40. package/cli/selftune/evolution/engines/replay-engine.ts +180 -0
  41. package/cli/selftune/evolution/evidence.ts +2 -6
  42. package/cli/selftune/evolution/evolve-body.ts +152 -38
  43. package/cli/selftune/evolution/evolve.ts +244 -52
  44. package/cli/selftune/evolution/rollback.ts +0 -1
  45. package/cli/selftune/evolution/validate-body.ts +111 -49
  46. package/cli/selftune/evolution/validate-host-replay.ts +510 -60
  47. package/cli/selftune/evolution/validate-proposal.ts +11 -150
  48. package/cli/selftune/evolution/validate-routing.ts +51 -108
  49. package/cli/selftune/evolution/validation-contract.ts +91 -0
  50. package/cli/selftune/grading/auto-grade.ts +11 -7
  51. package/cli/selftune/grading/grade-session.ts +10 -16
  52. package/cli/selftune/hooks/skill-eval.ts +2 -1
  53. package/cli/selftune/hooks-shared/types.ts +1 -0
  54. package/cli/selftune/index.ts +58 -15
  55. package/cli/selftune/ingestors/claude-replay.ts +15 -10
  56. package/cli/selftune/ingestors/codex-wrapper.ts +3 -3
  57. package/cli/selftune/ingestors/opencode-ingest.ts +2 -2
  58. package/cli/selftune/ingestors/pi-ingest.ts +727 -0
  59. package/cli/selftune/init.ts +38 -4
  60. package/cli/selftune/localdb/direct-write.ts +120 -1
  61. package/cli/selftune/localdb/materialize.ts +6 -7
  62. package/cli/selftune/localdb/queries/cron.ts +34 -0
  63. package/cli/selftune/localdb/queries/dashboard.ts +834 -0
  64. package/cli/selftune/localdb/queries/evolution.ts +158 -0
  65. package/cli/selftune/localdb/queries/execution.ts +133 -0
  66. package/cli/selftune/localdb/queries/json.ts +18 -0
  67. package/cli/selftune/localdb/queries/monitoring.ts +263 -0
  68. package/cli/selftune/localdb/queries/raw.ts +95 -0
  69. package/cli/selftune/localdb/queries/staging.ts +270 -0
  70. package/cli/selftune/localdb/queries/trust.ts +392 -0
  71. package/cli/selftune/localdb/queries.ts +60 -2162
  72. package/cli/selftune/localdb/schema.ts +59 -0
  73. package/cli/selftune/monitoring/watch.ts +96 -29
  74. package/cli/selftune/normalization.ts +3 -0
  75. package/cli/selftune/observability.ts +12 -3
  76. package/cli/selftune/orchestrate/cli.ts +161 -0
  77. package/cli/selftune/orchestrate/execute.ts +295 -0
  78. package/cli/selftune/orchestrate/finalize.ts +157 -0
  79. package/cli/selftune/orchestrate/locks.ts +40 -0
  80. package/cli/selftune/orchestrate/plan.ts +131 -0
  81. package/cli/selftune/orchestrate/post-run.ts +59 -0
  82. package/cli/selftune/orchestrate/prepare.ts +334 -0
  83. package/cli/selftune/orchestrate/report.ts +182 -0
  84. package/cli/selftune/orchestrate/runtime.ts +120 -0
  85. package/cli/selftune/orchestrate/signals.ts +48 -0
  86. package/cli/selftune/orchestrate.ts +162 -1142
  87. package/cli/selftune/registry/client.ts +74 -0
  88. package/cli/selftune/registry/history.ts +54 -0
  89. package/cli/selftune/registry/index.ts +90 -0
  90. package/cli/selftune/registry/install.ts +141 -0
  91. package/cli/selftune/registry/list.ts +44 -0
  92. package/cli/selftune/registry/push.ts +171 -0
  93. package/cli/selftune/registry/rollback.ts +49 -0
  94. package/cli/selftune/registry/status.ts +62 -0
  95. package/cli/selftune/registry/sync.ts +125 -0
  96. package/cli/selftune/repair/skill-usage.ts +9 -3
  97. package/cli/selftune/routes/overview.ts +5 -2
  98. package/cli/selftune/routes/skill-report.ts +15 -2
  99. package/cli/selftune/schedule.ts +5 -5
  100. package/cli/selftune/status.ts +70 -2
  101. package/cli/selftune/sync.ts +127 -23
  102. package/cli/selftune/testing-readiness.ts +597 -0
  103. package/cli/selftune/types.ts +46 -5
  104. package/cli/selftune/uninstall.ts +2 -1
  105. package/cli/selftune/utils/canonical-log.ts +1 -9
  106. package/cli/selftune/utils/cli-error.ts +9 -0
  107. package/cli/selftune/utils/jsonl.ts +1 -30
  108. package/cli/selftune/utils/llm-call.ts +126 -6
  109. package/cli/selftune/utils/skill-discovery.ts +24 -0
  110. package/cli/selftune/workflows/proposals.ts +184 -0
  111. package/cli/selftune/workflows/skill-scaffold.ts +241 -0
  112. package/cli/selftune/workflows/workflows.ts +100 -26
  113. package/node_modules/@selftune/telemetry-contract/fixtures/complete-push.ts +1 -1
  114. package/node_modules/@selftune/telemetry-contract/fixtures/evidence-only-push.ts +2 -2
  115. package/node_modules/@selftune/telemetry-contract/fixtures/golden.test.ts +0 -1
  116. package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
  117. package/node_modules/@selftune/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +2 -2
  118. package/node_modules/@selftune/telemetry-contract/package.json +1 -1
  119. package/node_modules/@selftune/telemetry-contract/src/index.ts +1 -0
  120. package/node_modules/@selftune/telemetry-contract/src/schemas.ts +63 -5
  121. package/node_modules/@selftune/telemetry-contract/src/types.ts +97 -7
  122. package/node_modules/@selftune/telemetry-contract/tests/compatibility.test.ts +0 -1
  123. package/package.json +25 -9
  124. package/packages/dashboard-core/AGENTS.md +18 -0
  125. package/packages/dashboard-core/README.md +30 -0
  126. package/packages/dashboard-core/index.ts +3 -0
  127. package/packages/dashboard-core/package.json +39 -0
  128. package/packages/dashboard-core/src/chrome/DashboardChrome.tsx +74 -0
  129. package/packages/dashboard-core/src/chrome/DashboardHeader.tsx +200 -0
  130. package/packages/dashboard-core/src/chrome/DashboardSidebar.tsx +219 -0
  131. package/packages/dashboard-core/src/chrome/RuntimeBadge.tsx +46 -0
  132. package/packages/dashboard-core/src/chrome/index.ts +14 -0
  133. package/packages/dashboard-core/src/chrome/types.ts +81 -0
  134. package/packages/dashboard-core/src/chrome/utils.ts +23 -0
  135. package/packages/dashboard-core/src/gates/FeatureGate.tsx +11 -0
  136. package/packages/dashboard-core/src/gates/LockedRoute.tsx +29 -0
  137. package/packages/dashboard-core/src/gates/UpgradeCard.tsx +89 -0
  138. package/packages/dashboard-core/src/gates/index.ts +3 -0
  139. package/packages/dashboard-core/src/host/DashboardHostProvider.tsx +62 -0
  140. package/packages/dashboard-core/src/host/adapter.ts +47 -0
  141. package/packages/dashboard-core/src/host/capabilities.ts +55 -0
  142. package/packages/dashboard-core/src/host/index.ts +3 -0
  143. package/packages/dashboard-core/src/models/analytics.ts +39 -0
  144. package/packages/dashboard-core/src/models/index.ts +4 -0
  145. package/packages/dashboard-core/src/models/overview.ts +98 -0
  146. package/packages/dashboard-core/src/models/runtime.ts +7 -0
  147. package/packages/dashboard-core/src/models/skills.ts +34 -0
  148. package/packages/dashboard-core/src/routes/index.ts +2 -0
  149. package/packages/dashboard-core/src/routes/manifest.test.ts +70 -0
  150. package/packages/dashboard-core/src/routes/manifest.ts +451 -0
  151. package/packages/dashboard-core/src/routes/types.ts +39 -0
  152. package/packages/dashboard-core/src/screens/analytics/AnalyticsScreen.tsx +278 -0
  153. package/packages/dashboard-core/src/screens/analytics/index.ts +1 -0
  154. package/packages/dashboard-core/src/screens/index.ts +37 -0
  155. package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.test.ts +101 -0
  156. package/packages/dashboard-core/src/screens/overview/OverviewComparisonSurface.tsx +393 -0
  157. package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.test.tsx +113 -0
  158. package/packages/dashboard-core/src/screens/overview/OverviewCompositionSurface.tsx +72 -0
  159. package/packages/dashboard-core/src/screens/overview/OverviewCoreSurface.tsx +71 -0
  160. package/packages/dashboard-core/src/screens/overview/OverviewOnboardingBanner.tsx +90 -0
  161. package/packages/dashboard-core/src/screens/overview/OverviewRunSummary.tsx +40 -0
  162. package/packages/dashboard-core/src/screens/overview/index.ts +16 -0
  163. package/packages/dashboard-core/src/screens/overview/types.ts +13 -0
  164. package/packages/dashboard-core/src/screens/skill-report/SkillReportDailyBreakdownSection.tsx +99 -0
  165. package/packages/dashboard-core/src/screens/skill-report/SkillReportDataQualityTabContent.tsx +35 -0
  166. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceRail.tsx +71 -0
  167. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceSection.tsx +63 -0
  168. package/packages/dashboard-core/src/screens/skill-report/SkillReportEvidenceTabContent.tsx +25 -0
  169. package/packages/dashboard-core/src/screens/skill-report/SkillReportInvocationsSection.tsx +24 -0
  170. package/packages/dashboard-core/src/screens/skill-report/SkillReportMissedQueriesSection.tsx +79 -0
  171. package/packages/dashboard-core/src/screens/skill-report/SkillReportScaffold.tsx +150 -0
  172. package/packages/dashboard-core/src/screens/skill-report/SkillReportSections.test.tsx +224 -0
  173. package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.test.tsx +76 -0
  174. package/packages/dashboard-core/src/screens/skill-report/SkillReportTabs.tsx +88 -0
  175. package/packages/dashboard-core/src/screens/skill-report/SkillReportTrendSection.tsx +33 -0
  176. package/packages/dashboard-core/src/screens/skill-report/SkillReportTrustBadge.tsx +67 -0
  177. package/packages/dashboard-core/src/screens/skill-report/index.ts +45 -0
  178. package/packages/dashboard-core/src/screens/skills/SkillsLibraryScreen.tsx +162 -0
  179. package/packages/dashboard-core/src/screens/skills/index.ts +6 -0
  180. package/packages/telemetry-contract/fixtures/complete-push.ts +1 -1
  181. package/packages/telemetry-contract/fixtures/evidence-only-push.ts +2 -2
  182. package/packages/telemetry-contract/fixtures/golden.test.ts +0 -1
  183. package/packages/telemetry-contract/fixtures/partial-push-no-sessions.ts +1 -1
  184. package/packages/telemetry-contract/fixtures/partial-push-unresolved-parents.ts +2 -2
  185. package/packages/telemetry-contract/package.json +1 -1
  186. package/packages/telemetry-contract/src/index.ts +1 -0
  187. package/packages/telemetry-contract/src/schemas.ts +63 -5
  188. package/packages/telemetry-contract/src/types.ts +97 -7
  189. package/packages/telemetry-contract/tests/compatibility.test.ts +0 -1
  190. package/packages/ui/AGENTS.md +16 -0
  191. package/packages/ui/README.md +1 -1
  192. package/packages/ui/package.json +1 -1
  193. package/packages/ui/src/components/ActivityTimeline.tsx +152 -168
  194. package/packages/ui/src/components/AnalyticsCharts.tsx +344 -0
  195. package/packages/ui/src/components/EvidenceViewer.tsx +229 -464
  196. package/packages/ui/src/components/EvolutionTimeline.tsx +34 -87
  197. package/packages/ui/src/components/InfoTip.tsx +1 -2
  198. package/packages/ui/src/components/InvocationsPanel.tsx +413 -0
  199. package/packages/ui/src/components/JobHistoryTimeline.tsx +156 -0
  200. package/packages/ui/src/components/OrchestrateRunsPanel.tsx +18 -36
  201. package/packages/ui/src/components/OverviewPanels.tsx +693 -0
  202. package/packages/ui/src/components/PipelineStatusBar.tsx +65 -0
  203. package/packages/ui/src/components/SkillReportGuide.tsx +215 -0
  204. package/packages/ui/src/components/SkillReportPanels.tsx +919 -0
  205. package/packages/ui/src/components/SkillsLibrary.tsx +437 -0
  206. package/packages/ui/src/components/index.ts +56 -1
  207. package/packages/ui/src/components/section-cards.tsx +18 -35
  208. package/packages/ui/src/components/skill-health-grid.tsx +47 -37
  209. package/packages/ui/src/lib/constants.tsx +0 -1
  210. package/packages/ui/src/primitives/card.tsx +1 -1
  211. package/packages/ui/src/primitives/checkbox.tsx +1 -1
  212. package/packages/ui/src/primitives/dropdown-menu.tsx +2 -2
  213. package/packages/ui/src/primitives/select.tsx +2 -2
  214. package/packages/ui/src/primitives/tabs.tsx +7 -6
  215. package/packages/ui/src/types.ts +182 -4
  216. package/skill/SKILL.md +130 -318
  217. package/skill/agents/diagnosis-analyst.md +3 -3
  218. package/skill/agents/evolution-reviewer.md +3 -3
  219. package/skill/agents/integration-guide.md +3 -3
  220. package/skill/agents/pattern-analyst.md +2 -2
  221. package/skill/references/cli-quick-reference.md +89 -0
  222. package/skill/references/creator-playbook.md +131 -0
  223. package/skill/references/examples.md +48 -0
  224. package/skill/references/troubleshooting.md +47 -0
  225. package/skill/references/version-history.md +1 -1
  226. package/skill/selftune.contribute.json +11 -0
  227. package/skill/{Workflows → workflows}/Baseline.md +20 -1
  228. package/skill/{Workflows → workflows}/Contribute.md +23 -10
  229. package/skill/{Workflows → workflows}/Contributions.md +13 -5
  230. package/skill/workflows/CreateTestDeploy.md +170 -0
  231. package/skill/{Workflows → workflows}/CreatorContributions.md +18 -6
  232. package/skill/{Workflows → workflows}/Cron.md +1 -1
  233. package/skill/{Workflows → workflows}/Dashboard.md +20 -0
  234. package/skill/{Workflows → workflows}/Doctor.md +1 -1
  235. package/skill/{Workflows → workflows}/Evals.md +67 -2
  236. package/skill/{Workflows → workflows}/Evolve.md +119 -30
  237. package/skill/{Workflows → workflows}/EvolveBody.md +41 -1
  238. package/skill/{Workflows → workflows}/Grade.md +1 -1
  239. package/skill/{Workflows → workflows}/Ingest.md +60 -2
  240. package/skill/{Workflows → workflows}/Initialize.md +16 -9
  241. package/skill/{Workflows → workflows}/Orchestrate.md +13 -3
  242. package/skill/{Workflows → workflows}/PlatformHooks.md +19 -3
  243. package/skill/workflows/Registry.md +99 -0
  244. package/skill/{Workflows → workflows}/Schedule.md +3 -3
  245. package/skill/workflows/SignalsDashboard.md +87 -0
  246. package/skill/{Workflows → workflows}/Sync.md +3 -1
  247. package/skill/{Workflows → workflows}/UnitTest.md +19 -0
  248. package/skill/{Workflows → workflows}/Watch.md +42 -2
  249. package/skill/{Workflows → workflows}/Workflows.md +39 -2
  250. package/apps/local-dashboard/dist/assets/index-D8O-RG1I.js +0 -60
  251. package/apps/local-dashboard/dist/assets/index-_EcLywDg.css +0 -1
  252. package/apps/local-dashboard/dist/assets/vendor-react-CKkiCskZ.js +0 -11
  253. package/apps/local-dashboard/dist/assets/vendor-ui-CGEmUayx.js +0 -12
  254. package/cli/selftune/utils/html.ts +0 -27
  255. package/packages/ui/src/components/RecentActivityFeed.tsx +0 -117
  256. /package/skill/{Workflows → workflows}/AlphaUpload.md +0 -0
  257. /package/skill/{Workflows → workflows}/AutoActivation.md +0 -0
  258. /package/skill/{Workflows → workflows}/Badge.md +0 -0
  259. /package/skill/{Workflows → workflows}/Composability.md +0 -0
  260. /package/skill/{Workflows → workflows}/EvolutionMemory.md +0 -0
  261. /package/skill/{Workflows → workflows}/ExportCanonical.md +0 -0
  262. /package/skill/{Workflows → workflows}/Hook.md +0 -0
  263. /package/skill/{Workflows → workflows}/ImportSkillsBench.md +0 -0
  264. /package/skill/{Workflows → workflows}/Quickstart.md +0 -0
  265. /package/skill/{Workflows → workflows}/Recover.md +0 -0
  266. /package/skill/{Workflows → workflows}/RepairSkillUsage.md +0 -0
  267. /package/skill/{Workflows → workflows}/Replay.md +0 -0
  268. /package/skill/{Workflows → workflows}/Rollback.md +0 -0
  269. /package/skill/{Workflows → workflows}/Telemetry.md +0 -0
  270. /package/skill/{Workflows → workflows}/Uninstall.md +0 -0
@@ -1,7 +1,7 @@
1
1
  export const CANONICAL_SCHEMA_VERSION = "2.0" as const;
2
2
  export type CanonicalSchemaVersion = typeof CANONICAL_SCHEMA_VERSION;
3
3
 
4
- export const CANONICAL_PLATFORMS = ["claude_code", "codex", "opencode", "openclaw"] as const;
4
+ export const CANONICAL_PLATFORMS = ["claude_code", "codex", "opencode", "openclaw", "pi"] as const;
5
5
  export type CanonicalPlatform = (typeof CANONICAL_PLATFORMS)[number];
6
6
 
7
7
  export const CANONICAL_CAPTURE_MODES = [
@@ -54,7 +54,7 @@ export const CANONICAL_RECORD_KINDS = [
54
54
  ] as const;
55
55
  export type CanonicalRecordKind = (typeof CANONICAL_RECORD_KINDS)[number];
56
56
 
57
- export interface CanonicalRawSourceRef {
57
+ export interface CanonicalRawSourceRef extends Record<string, unknown> {
58
58
  path?: string;
59
59
  line?: number;
60
60
  event_type?: string;
@@ -62,7 +62,7 @@ export interface CanonicalRawSourceRef {
62
62
  metadata?: Record<string, unknown>;
63
63
  }
64
64
 
65
- export interface CanonicalRecordBase {
65
+ export interface CanonicalRecordBase extends Record<string, unknown> {
66
66
  record_kind: CanonicalRecordKind;
67
67
  schema_version: CanonicalSchemaVersion;
68
68
  normalizer_version: string;
@@ -146,15 +146,14 @@ export interface CanonicalExecutionFactRecord extends CanonicalSessionRecordBase
146
146
  cached_input_tokens?: number;
147
147
  reasoning_output_tokens?: number;
148
148
  cost_usd?: number;
149
- duration_ms?: number;
150
149
  files_changed?: number;
151
150
  lines_added?: number;
152
151
  lines_removed?: number;
153
152
  lines_modified?: number;
154
- /** Count of output-producing tool calls (Write, Edit, WebFetch, WebSearch, Skill, Agent). */
155
153
  artifact_count?: number;
156
- /** Inferred session type based on tool distribution. */
157
- session_type?: "dev" | "research" | "content" | "mixed";
154
+ session_type?: string;
155
+ agent_summary?: string;
156
+ duration_ms?: number;
158
157
  completion_status?: CanonicalCompletionStatus;
159
158
  end_reason?: string;
160
159
  }
@@ -168,9 +167,100 @@ export interface CanonicalNormalizationRunRecord extends CanonicalRecordBase {
168
167
  repair_applied: boolean;
169
168
  }
170
169
 
170
+ export interface CanonicalEvolutionEvidenceRecord {
171
+ evidence_id?: string;
172
+ timestamp?: string;
173
+ proposal_id?: string;
174
+ skill_name: string;
175
+ skill_path?: string;
176
+ target: string;
177
+ stage: string;
178
+ rationale?: string;
179
+ confidence?: number;
180
+ details?: string;
181
+ original_text?: string;
182
+ proposed_text?: string;
183
+ eval_set_json?: unknown;
184
+ validation_json?: unknown;
185
+ raw_source_ref?: CanonicalRawSourceRef;
186
+ }
187
+
188
+ export interface CanonicalGradingResultRecord {
189
+ grading_id: string;
190
+ session_id: string;
191
+ skill_name: string;
192
+ transcript_path?: string | null;
193
+ graded_at: string;
194
+ pass_rate?: number | null;
195
+ mean_score?: number | null;
196
+ score_std_dev?: number | null;
197
+ passed_count?: number | null;
198
+ failed_count?: number | null;
199
+ total_count?: number | null;
200
+ expectations_json?: string | null;
201
+ claims_json?: string | null;
202
+ eval_feedback_json?: string | null;
203
+ failure_feedback_json?: string | null;
204
+ execution_metrics_json?: string | null;
205
+ }
206
+
207
+ export interface CanonicalImprovementSignalRecord {
208
+ signal_id: string;
209
+ timestamp: string;
210
+ session_id: string;
211
+ query: string;
212
+ signal_type: string;
213
+ mentioned_skill?: string | null;
214
+ consumed: boolean;
215
+ consumed_at?: string | null;
216
+ consumed_by_run?: string | null;
217
+ }
218
+
171
219
  export type CanonicalRecord =
172
220
  | CanonicalSessionRecord
173
221
  | CanonicalPromptRecord
174
222
  | CanonicalSkillInvocationRecord
175
223
  | CanonicalExecutionFactRecord
176
224
  | CanonicalNormalizationRunRecord;
225
+
226
+ export interface PushOrchestrateRunRecord {
227
+ run_id: string;
228
+ timestamp: string;
229
+ elapsed_ms: number;
230
+ dry_run: boolean;
231
+ approval_mode: "auto" | "review";
232
+ total_skills: number;
233
+ evaluated: number;
234
+ evolved: number;
235
+ deployed: number;
236
+ watched: number;
237
+ skipped: number;
238
+ skill_actions: Array<{
239
+ skill: string;
240
+ action: "evolve" | "watch" | "skip";
241
+ reason: string;
242
+ deployed?: boolean;
243
+ rolledBack?: boolean;
244
+ alert?: string | null;
245
+ elapsed_ms?: number;
246
+ llm_calls?: number;
247
+ }>;
248
+ }
249
+
250
+ export interface PushPayloadV2 {
251
+ schema_version: CanonicalSchemaVersion;
252
+ client_version: string;
253
+ push_id: string;
254
+ normalizer_version: string;
255
+ canonical: {
256
+ sessions: CanonicalSessionRecord[];
257
+ prompts: CanonicalPromptRecord[];
258
+ skill_invocations: CanonicalSkillInvocationRecord[];
259
+ execution_facts: CanonicalExecutionFactRecord[];
260
+ normalization_runs: CanonicalNormalizationRunRecord[];
261
+ evolution_evidence?: CanonicalEvolutionEvidenceRecord[];
262
+ orchestrate_runs?: PushOrchestrateRunRecord[];
263
+ grading_results?: CanonicalGradingResultRecord[];
264
+ improvement_signals?: CanonicalImprovementSignalRecord[];
265
+ };
266
+ }
@@ -1,5 +1,4 @@
1
1
  import { describe, expect, test } from "bun:test";
2
-
3
2
  import { completePush } from "../fixtures/complete-push.js";
4
3
  import { evidenceOnlyPush } from "../fixtures/evidence-only-push.js";
5
4
  import { partialPushNoSessions } from "../fixtures/partial-push-no-sessions.js";
package/package.json CHANGED
@@ -1,24 +1,35 @@
1
1
  {
2
2
  "name": "selftune",
3
- "version": "0.2.22",
4
- "description": "Self-improving skills CLI for AI agents",
3
+ "version": "0.2.24",
4
+ "description": "Skill-level observability and self-improvement for AI agents — monitors skill routing, detects missed triggers, and evolves descriptions automatically",
5
5
  "keywords": [
6
6
  "agent",
7
+ "agent-skills",
8
+ "ai-agent",
9
+ "ai-observability",
7
10
  "bun",
8
11
  "claude-code",
9
12
  "cli",
13
+ "cline",
10
14
  "codex",
11
15
  "eval",
16
+ "evals",
12
17
  "evolution",
13
18
  "grading",
19
+ "llm",
20
+ "observability",
14
21
  "opencode",
15
22
  "self-improving",
16
23
  "selftune",
17
24
  "skill",
25
+ "skill-evals",
26
+ "skill-observability",
27
+ "skill-routing",
28
+ "skill-testing",
18
29
  "telemetry",
19
30
  "typescript"
20
31
  ],
21
- "homepage": "https://github.com/selftune-dev/selftune#readme",
32
+ "homepage": "https://selftune.dev",
22
33
  "bugs": {
23
34
  "url": "https://github.com/selftune-dev/selftune/issues"
24
35
  },
@@ -44,6 +55,7 @@
44
55
  "bin/",
45
56
  "cli/selftune/",
46
57
  "apps/local-dashboard/dist/",
58
+ "packages/dashboard-core/",
47
59
  "packages/telemetry-contract/",
48
60
  "packages/ui/",
49
61
  "templates/",
@@ -53,9 +65,9 @@
53
65
  ],
54
66
  "type": "module",
55
67
  "scripts": {
56
- "dev": "trap 'kill 0' EXIT; bun --watch run cli/selftune/dashboard-server.ts --port 7888 --runtime-mode dev-server & sleep 1 && cd apps/local-dashboard && bunx vite --strictPort",
57
- "dev:server": "bun --watch run cli/selftune/dashboard-server.ts --port 7888 --runtime-mode dev-server",
58
- "dev:dashboard": "bun run cli/selftune/index.ts dashboard --port 7888 --no-open",
68
+ "dev": "cd apps/local-dashboard && bun run dev",
69
+ "dev:server": "sh -c 'dashboard_port=${DASHBOARD_PORT:-7888}; bun --watch run cli/selftune/dashboard-server.ts --port $dashboard_port --runtime-mode dev-server'",
70
+ "dev:dashboard": "sh -c 'dashboard_port=${DASHBOARD_PORT:-7888}; bun run cli/selftune/index.ts dashboard --port $dashboard_port --no-open'",
59
71
  "lint": "bunx oxlint",
60
72
  "lint:fix": "bunx oxlint --fix",
61
73
  "format": "bunx oxfmt",
@@ -71,17 +83,21 @@
71
83
  "sync-version": "bun run scripts/sync-skill-version.ts",
72
84
  "validate:subagents": "bun run scripts/validate-subagent-docs.ts",
73
85
  "prepublishOnly": "bun run sync-version && bun run build:dashboard",
86
+ "typecheck:runtime": "bunx tsc --noEmit -p tsconfig.runtime.json",
74
87
  "typecheck:dashboard": "cd apps/local-dashboard && bunx tsc --noEmit",
75
- "check": "bun run lint && bun run format:check && bun run lint:arch && bun run typecheck:dashboard && bun run test",
88
+ "check": "bun run lint && bun run format:check && bun run lint:arch && bun run typecheck:runtime && bun run typecheck:dashboard && bun run test",
76
89
  "prepare": "bunx lefthook install || true",
77
90
  "start": "bun run cli/selftune/index.ts --help"
78
91
  },
79
92
  "dependencies": {
80
- "@selftune/telemetry-contract": "file:packages/telemetry-contract"
93
+ "@selftune/telemetry-contract": "file:packages/telemetry-contract",
94
+ "react-markdown": "^10.1.0",
95
+ "zod": "^4.3.6"
81
96
  },
82
97
  "devDependencies": {
83
98
  "@evilmartians/lefthook": "^1.13.6",
84
- "@types/bun": "^1.1.0",
99
+ "@types/bun": "^1.3.11",
100
+ "bun-types": "^1.3.11",
85
101
  "oxfmt": "^0.41.0",
86
102
  "oxlint": "^1.56.0"
87
103
  },
@@ -0,0 +1,18 @@
1
+ # @selftune/dashboard-core
2
+
3
+ Shared dashboard application layer used by both the cloud dashboard and the local OSS dashboard. Canonical copy lives here; synced to `oss/selftune/packages/dashboard-core` via `scripts/sync-embedded-shared.sh`.
4
+
5
+ | Directory | Contents |
6
+ |-----------|----------|
7
+ | `src/host/` | Capability model, host adapter contracts, provider/context hooks |
8
+ | `src/models/` | Normalized view models shared across hosts |
9
+ | `src/routes/` | Route definition and route access helpers |
10
+ | `src/chrome/` | Shared shell, sidebar, header, runtime badge, and chrome types |
11
+ | `src/gates/` | Shared feature gates, locked-route surfaces, and upgrade CTAs |
12
+ | `src/screens/` | Shared screen implementations; analytics, the overview autonomy/comparison/support surfaces, skills library, and the skill report scaffold/trust chrome are extracted |
13
+
14
+ **Exports:** `.`, `./host`, `./models`, `./routes`, `./chrome`, `./gates`, `./screens`
15
+
16
+ **Dependencies:** `@selftune/ui`, `lucide-react`, `react` (peer), `react-dom` (peer)
17
+
18
+ **Important:** Do NOT edit `oss/selftune/packages/dashboard-core/` directly. Edit here and run `scripts/sync-embedded-shared.sh`.
@@ -0,0 +1,30 @@
1
+ # @selftune/dashboard-core
2
+
3
+ Shared dashboard application layer for SelfTune cloud and local hosts.
4
+
5
+ This package owns:
6
+
7
+ - capability and entitlement contracts
8
+ - host adapter interfaces
9
+ - normalized dashboard view models
10
+ - shared route definition helpers
11
+ - shared dashboard chrome primitives used by cloud and local hosts
12
+ - shared feature gates and locked-route upgrade surfaces
13
+ - shared screen implementations, including analytics, the overview autonomy/comparison/support surfaces, skills library, and the shared skill report scaffold/trust chrome
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import {
19
+ DashboardChrome,
20
+ DashboardHostProvider,
21
+ canUseFeature,
22
+ type Capabilities,
23
+ type DashboardHostAdapter,
24
+ } from "@selftune/dashboard-core";
25
+ ```
26
+
27
+ ## OSS Mirror
28
+
29
+ This package is canonical in the root `packages/` directory and mirrored into
30
+ `oss/selftune/packages/dashboard-core` via `scripts/sync-embedded-shared.sh`.
@@ -0,0 +1,3 @@
1
+ export * from "./src/host/index";
2
+ export * from "./src/models/index";
3
+ export * from "./src/routes/index";
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@selftune/dashboard-core",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "Shared dashboard application layer for selftune cloud and local hosts",
6
+ "license": "MIT",
7
+ "author": "Daniel Petro",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/selftune-dev/selftune.git",
11
+ "directory": "packages/dashboard-core"
12
+ },
13
+ "type": "module",
14
+ "exports": {
15
+ ".": "./index.ts",
16
+ "./host": "./src/host/index.ts",
17
+ "./models": "./src/models/index.ts",
18
+ "./routes": "./src/routes/index.ts",
19
+ "./chrome": "./src/chrome/index.ts",
20
+ "./gates": "./src/gates/index.ts",
21
+ "./screens": "./src/screens/index.ts",
22
+ "./screens/analytics": "./src/screens/analytics/index.ts",
23
+ "./screens/overview": "./src/screens/overview/index.ts",
24
+ "./screens/skill-report": "./src/screens/skill-report/index.ts",
25
+ "./screens/skills": "./src/screens/skills/index.ts"
26
+ },
27
+ "dependencies": {
28
+ "@selftune/ui": "workspace:*",
29
+ "lucide-react": "^0.576.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^19.0.0",
33
+ "@types/react-dom": "^19.0.0"
34
+ },
35
+ "peerDependencies": {
36
+ "react": "^19.0.0",
37
+ "react-dom": "^19.0.0"
38
+ }
39
+ }
@@ -0,0 +1,74 @@
1
+ "use client";
2
+
3
+ import { PlayIcon } from "lucide-react";
4
+ import { useState } from "react";
5
+
6
+ import { TooltipProvider } from "@selftune/ui/primitives";
7
+
8
+ import { DashboardHeader } from "./DashboardHeader";
9
+ import { DashboardSidebar } from "./DashboardSidebar";
10
+ import { cn } from "./utils";
11
+ import type { DashboardChromeProps } from "./types";
12
+
13
+ const DEFAULT_CONTENT_CLASS_NAME = "@container/main mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8";
14
+
15
+ export function DashboardChrome({
16
+ brand,
17
+ navItems,
18
+ renderLink,
19
+ headerMeta,
20
+ searchItems = [],
21
+ headerUser,
22
+ sidebarUser,
23
+ sidebarAction,
24
+ onSignOut,
25
+ overlay,
26
+ contentClassName,
27
+ children,
28
+ }: DashboardChromeProps) {
29
+ const [mobileOpen, setMobileOpen] = useState(false);
30
+
31
+ const content =
32
+ contentClassName === null ? (
33
+ children
34
+ ) : (
35
+ <div className={cn(contentClassName ?? DEFAULT_CONTENT_CLASS_NAME)}>{children}</div>
36
+ );
37
+
38
+ return (
39
+ <TooltipProvider>
40
+ <div className="min-h-screen bg-background">
41
+ <DashboardSidebar
42
+ brand={brand}
43
+ navItems={navItems}
44
+ renderLink={renderLink}
45
+ sidebarAction={
46
+ sidebarAction ?? {
47
+ label: "Run Evolution",
48
+ tooltip: "Dashboard-triggered evolution is not available yet.",
49
+ icon: <PlayIcon className="size-4" />,
50
+ disabled: true,
51
+ }
52
+ }
53
+ sidebarUser={sidebarUser}
54
+ onSignOut={onSignOut}
55
+ mobileOpen={mobileOpen}
56
+ onMobileOpenChange={setMobileOpen}
57
+ />
58
+
59
+ <div className="min-h-screen lg:pl-64">
60
+ <DashboardHeader
61
+ renderLink={renderLink}
62
+ headerMeta={headerMeta}
63
+ searchItems={searchItems}
64
+ headerUser={headerUser}
65
+ onToggleSidebar={() => setMobileOpen((open) => !open)}
66
+ />
67
+ <main className="min-h-[calc(100vh-4rem)]">{content}</main>
68
+ </div>
69
+
70
+ {overlay}
71
+ </div>
72
+ </TooltipProvider>
73
+ );
74
+ }
@@ -0,0 +1,200 @@
1
+ "use client";
2
+
3
+ import { ArrowLeftIcon, BellIcon, BoltIcon, MenuIcon, SearchIcon, UserIcon } from "lucide-react";
4
+ import { useDeferredValue, useRef, useState } from "react";
5
+
6
+ import type { DashboardUser } from "../host/index";
7
+ import { getUserInitials, matchesSearchItem } from "./utils";
8
+ import type { DashboardHeaderMeta, DashboardLinkRenderer, DashboardSearchItem } from "./types";
9
+
10
+ interface DashboardHeaderProps {
11
+ renderLink: DashboardLinkRenderer;
12
+ headerMeta: DashboardHeaderMeta;
13
+ searchItems: DashboardSearchItem[];
14
+ headerUser?: DashboardUser;
15
+ onToggleSidebar(): void;
16
+ }
17
+
18
+ export function DashboardHeader({
19
+ renderLink,
20
+ headerMeta,
21
+ searchItems,
22
+ headerUser,
23
+ onToggleSidebar,
24
+ }: DashboardHeaderProps) {
25
+ const [query, setQuery] = useState("");
26
+ const [open, setOpen] = useState(false);
27
+ const suppressBlurRef = useRef(false);
28
+ const deferredQuery = useDeferredValue(query);
29
+
30
+ const filteredItems = searchItems
31
+ .filter((item) => matchesSearchItem(item, deferredQuery))
32
+ .slice(0, deferredQuery.trim() ? 12 : 8);
33
+
34
+ const groups = new Map<string, DashboardSearchItem[]>();
35
+ for (const item of filteredItems) {
36
+ const existing = groups.get(item.group) ?? [];
37
+ existing.push(item);
38
+ groups.set(item.group, existing);
39
+ }
40
+
41
+ return (
42
+ <header className="sticky top-0 z-40 border-b border-border/10 bg-background/80 backdrop-blur-xl">
43
+ <div className="flex h-16 items-center justify-between gap-4 px-4 lg:px-8">
44
+ <div className="flex min-w-0 flex-1 items-center gap-3 lg:gap-4">
45
+ <button
46
+ type="button"
47
+ className="rounded-lg bg-card p-2 text-foreground lg:hidden"
48
+ onClick={onToggleSidebar}
49
+ aria-label="Toggle sidebar"
50
+ >
51
+ <MenuIcon className="size-5" />
52
+ </button>
53
+
54
+ {headerMeta.backHref && headerMeta.backLabel
55
+ ? renderLink({
56
+ href: headerMeta.backHref,
57
+ className:
58
+ "inline-flex items-center gap-1 font-headline text-[10px] uppercase tracking-[0.2em] text-slate-500 transition-colors hover:text-primary",
59
+ children: (
60
+ <>
61
+ <ArrowLeftIcon className="size-3" />
62
+ {headerMeta.backLabel}
63
+ </>
64
+ ),
65
+ })
66
+ : null}
67
+
68
+ <div className="hidden xl:flex items-center gap-3 rounded-full border border-border/15 bg-card/60 px-3 py-1.5 text-sm shadow-[0_10px_40px_rgba(0,0,0,0.12)]">
69
+ {headerMeta.icon ? (
70
+ <span className="shrink-0 text-primary">{headerMeta.icon}</span>
71
+ ) : null}
72
+ <div className="flex min-w-0 items-center gap-2">
73
+ <span className="font-headline text-[10px] uppercase tracking-[0.18em] text-slate-500">
74
+ {headerMeta.badge ?? "View"}
75
+ </span>
76
+ <span className="truncate font-medium text-foreground">{headerMeta.title}</span>
77
+ </div>
78
+ </div>
79
+
80
+ <div className="relative w-full max-w-xl">
81
+ <SearchIcon className="pointer-events-none absolute left-3 top-1/2 z-10 size-4 -translate-y-1/2 text-slate-400" />
82
+ <input
83
+ value={query}
84
+ onChange={(event) => setQuery(event.target.value)}
85
+ onFocus={() => setOpen(true)}
86
+ onBlur={() => {
87
+ if (suppressBlurRef.current) {
88
+ suppressBlurRef.current = false;
89
+ return;
90
+ }
91
+ setOpen(false);
92
+ }}
93
+ placeholder="Search skills or pages..."
94
+ className="h-9 w-full rounded-full border border-border/10 bg-input/50 pl-10 pr-4 text-sm text-foreground outline-none transition focus:border-primary/30 focus:ring-1 focus:ring-primary/40 placeholder:text-slate-500"
95
+ />
96
+
97
+ {open ? (
98
+ <div className="absolute left-0 right-0 top-full z-50 mt-2 max-h-80 overflow-y-auto rounded-2xl border border-border/15 bg-card shadow-[0_20px_60px_rgba(0,0,0,0.35)] backdrop-blur-xl">
99
+ {filteredItems.length === 0 ? (
100
+ <div className="px-4 py-5 text-sm text-muted-foreground">No results found.</div>
101
+ ) : (
102
+ Array.from(groups.entries()).map(([group, items]) => (
103
+ <div key={group} className="border-b border-border/10 last:border-b-0">
104
+ <div className="px-4 pt-3 text-[10px] uppercase tracking-[0.18em] text-slate-500">
105
+ {group}
106
+ </div>
107
+ <div className="p-2">
108
+ {items.map((item) => (
109
+ <button
110
+ key={item.id}
111
+ type="button"
112
+ onMouseDown={(event) => {
113
+ event.preventDefault();
114
+ suppressBlurRef.current = true;
115
+ }}
116
+ onClick={() => {
117
+ item.onSelect();
118
+ setOpen(false);
119
+ setQuery("");
120
+ }}
121
+ className="flex w-full items-center gap-3 rounded-xl px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40"
122
+ >
123
+ {item.leading ? (
124
+ <span className="shrink-0">{item.leading}</span>
125
+ ) : (
126
+ <span className="shrink-0 text-slate-400">
127
+ {item.meta ? "•" : ""}
128
+ </span>
129
+ )}
130
+ <div className="min-w-0 flex-1">
131
+ <div className="truncate text-foreground">{item.label}</div>
132
+ {item.meta ? (
133
+ <div className="truncate text-xs text-muted-foreground">
134
+ {item.meta}
135
+ </div>
136
+ ) : null}
137
+ </div>
138
+ {item.trailing ? (
139
+ <span className="shrink-0 text-xs text-muted-foreground">
140
+ {item.trailing}
141
+ </span>
142
+ ) : null}
143
+ </button>
144
+ ))}
145
+ </div>
146
+ </div>
147
+ ))
148
+ )}
149
+ </div>
150
+ ) : null}
151
+ </div>
152
+ </div>
153
+
154
+ <div className="hidden items-center gap-4 sm:flex lg:gap-6">
155
+ <div className="flex items-center gap-4 text-slate-400">
156
+ <span className="relative" aria-hidden="true">
157
+ <BellIcon className="size-4" />
158
+ <span className="absolute -right-0.5 -top-0.5 size-2 rounded-full border-2 border-background bg-primary shadow-[0_0_6px_color-mix(in_srgb,var(--primary)_50%,transparent)]" />
159
+ </span>
160
+ <BoltIcon className="size-4" aria-hidden="true" />
161
+ </div>
162
+
163
+ {headerUser ? (
164
+ <>
165
+ <div className="h-8 w-px bg-border/20" />
166
+ <div className="flex items-center gap-3">
167
+ <div className="hidden text-right md:block">
168
+ <div className="font-headline text-[10px] uppercase tracking-widest text-slate-400">
169
+ {headerUser.name}
170
+ </div>
171
+ <div className="text-[10px] uppercase tracking-widest text-primary">
172
+ {headerUser.subtitle ?? headerUser.email ?? "Active"}
173
+ </div>
174
+ </div>
175
+ {headerUser.image ? (
176
+ // eslint-disable-next-line @next/next/no-img-element
177
+ <img
178
+ src={headerUser.image}
179
+ alt={headerUser.name}
180
+ className="size-8 rounded-full"
181
+ />
182
+ ) : (
183
+ <div className="flex size-8 items-center justify-center rounded-full border border-primary/20 bg-card text-primary">
184
+ {headerUser.name ? (
185
+ <span className="text-xs font-medium">
186
+ {getUserInitials(headerUser.name)}
187
+ </span>
188
+ ) : (
189
+ <UserIcon className="size-4" />
190
+ )}
191
+ </div>
192
+ )}
193
+ </div>
194
+ </>
195
+ ) : null}
196
+ </div>
197
+ </div>
198
+ </header>
199
+ );
200
+ }