selftune 0.2.23 → 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 (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-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/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
@@ -8,13 +8,14 @@
8
8
  * - cliMain() (reads logs, discovers workflows, prints output or saves)
9
9
  */
10
10
 
11
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
12
12
  import { parseArgs } from "node:util";
13
13
 
14
14
  import { getDb } from "../localdb/db.js";
15
15
  import { querySessionTelemetry, querySkillUsageRecords } from "../localdb/queries.js";
16
16
  import type {
17
17
  CodifiedWorkflow,
18
+ DiscoveredWorkflow,
18
19
  SessionTelemetryRecord,
19
20
  SkillUsageRecord,
20
21
  WorkflowDiscoveryReport,
@@ -22,6 +23,38 @@ import type {
22
23
  import { CLIError } from "../utils/cli-error.js";
23
24
  import { discoverWorkflows } from "./discover.js";
24
25
  import { appendWorkflow } from "./skill-md-writer.js";
26
+ import { buildWorkflowSkillDraft, formatWorkflowSkillDraft } from "./skill-scaffold.js";
27
+
28
+ function resolveWorkflowSelection(
29
+ report: WorkflowDiscoveryReport,
30
+ selection: string | undefined,
31
+ ): DiscoveredWorkflow {
32
+ if (!selection) {
33
+ throw new CLIError(
34
+ "Usage: selftune workflows <save|scaffold> <name-or-index>",
35
+ "MISSING_FLAG",
36
+ "Provide a workflow name or index (e.g., selftune workflows scaffold 1).",
37
+ );
38
+ }
39
+
40
+ let workflow = report.workflows.find((w) => w.workflow_id === selection);
41
+ if (!workflow) {
42
+ const idx = Number.parseInt(selection, 10);
43
+ if (!Number.isNaN(idx) && idx >= 1 && idx <= report.workflows.length) {
44
+ workflow = report.workflows[idx - 1];
45
+ }
46
+ }
47
+
48
+ if (!workflow) {
49
+ throw new CLIError(
50
+ `No workflow found matching "${selection}".`,
51
+ "INVALID_FLAG",
52
+ "Run 'selftune workflows' to see discovered workflows and their indices.",
53
+ );
54
+ }
55
+
56
+ return workflow;
57
+ }
25
58
 
26
59
  // ---------------------------------------------------------------------------
27
60
  // formatWorkflows — pure formatter
@@ -69,12 +102,41 @@ export async function cliMain(): Promise<void> {
69
102
  window: { type: "string" },
70
103
  skill: { type: "string" },
71
104
  "skill-path": { type: "string" },
105
+ "output-dir": { type: "string" },
106
+ "skill-name": { type: "string" },
107
+ description: { type: "string" },
108
+ write: { type: "boolean" },
109
+ force: { type: "boolean" },
72
110
  json: { type: "boolean" },
111
+ help: { type: "boolean", short: "h" },
73
112
  },
74
113
  strict: true,
75
114
  allowPositionals: true,
76
115
  });
77
116
 
117
+ if (values.help) {
118
+ console.log(`selftune workflows — Discover repeated multi-skill patterns
119
+
120
+ Usage:
121
+ selftune workflows [options]
122
+ selftune workflows save <name-or-index> [--skill-path <path>]
123
+ selftune workflows scaffold <name-or-index> [--output-dir <path>] [--skill-name <name>] [--description <text>] [--write] [--force] [--json]
124
+
125
+ Options:
126
+ --min-occurrences <n> Minimum workflow frequency to show (default: 3)
127
+ --window <n> Only analyze the most recent N sessions
128
+ --skill <name> Only show workflows containing the named skill
129
+ --skill-path <path> Target SKILL.md for the save subcommand
130
+ --output-dir <path> Target skill registry dir for scaffold previews/writes
131
+ --skill-name <name> Override the generated draft skill name
132
+ --description <text> Override the generated draft skill description
133
+ --write Persist the scaffolded draft skill to disk
134
+ --force Overwrite an existing scaffold path when combined with --write
135
+ --json Emit machine-readable JSON
136
+ -h, --help Show this help message`);
137
+ process.exit(0);
138
+ }
139
+
78
140
  const subcommand = positionals[0];
79
141
  const minOccurrences = values["min-occurrences"]
80
142
  ? Number.parseInt(values["min-occurrences"], 10)
@@ -101,31 +163,7 @@ export async function cliMain(): Promise<void> {
101
163
 
102
164
  if (subcommand === "save") {
103
165
  // Save subcommand: find workflow, append to SKILL.md
104
- const nameArg = positionals[1];
105
- if (!nameArg) {
106
- throw new CLIError(
107
- "Usage: selftune workflows save <name-or-index>",
108
- "MISSING_FLAG",
109
- "Provide a workflow name or index (e.g., selftune workflows save 1).",
110
- );
111
- }
112
-
113
- // Match by numeric index (1-based) or workflow_id
114
- let workflow = report.workflows.find((w) => w.workflow_id === nameArg);
115
- if (!workflow) {
116
- const idx = Number.parseInt(nameArg, 10);
117
- if (!Number.isNaN(idx) && idx >= 1 && idx <= report.workflows.length) {
118
- workflow = report.workflows[idx - 1];
119
- }
120
- }
121
-
122
- if (!workflow) {
123
- throw new CLIError(
124
- `No workflow found matching "${nameArg}".`,
125
- "INVALID_FLAG",
126
- "Run 'selftune workflows' to see discovered workflows and their indices.",
127
- );
128
- }
166
+ const workflow = resolveWorkflowSelection(report, positionals[1]);
129
167
 
130
168
  // Determine SKILL.md path
131
169
  let skillPath = values["skill-path"];
@@ -187,6 +225,42 @@ export async function cliMain(): Promise<void> {
187
225
  return;
188
226
  }
189
227
 
228
+ if (subcommand === "scaffold") {
229
+ const workflow = resolveWorkflowSelection(report, positionals[1]);
230
+ const draft = buildWorkflowSkillDraft(workflow, {
231
+ outputDir: values["output-dir"],
232
+ skillName: values["skill-name"],
233
+ description: values.description,
234
+ });
235
+
236
+ if (values.write) {
237
+ if (existsSync(draft.skill_path) && !values.force) {
238
+ throw new CLIError(
239
+ `Refusing to overwrite existing draft at ${draft.skill_path}.`,
240
+ "FILE_EXISTS",
241
+ "Re-run with --force to overwrite the existing draft skill.",
242
+ );
243
+ }
244
+
245
+ mkdirSync(draft.skill_dir, { recursive: true });
246
+ writeFileSync(draft.skill_path, draft.content, "utf-8");
247
+
248
+ if (values.json || !process.stdout.isTTY) {
249
+ console.log(JSON.stringify({ ...draft, written: true }, null, 2));
250
+ } else {
251
+ console.log(`Scaffolded skill "${draft.skill_name}" to ${draft.skill_path}`);
252
+ }
253
+ return;
254
+ }
255
+
256
+ if (values.json || !process.stdout.isTTY) {
257
+ console.log(JSON.stringify({ ...draft, written: false }, null, 2));
258
+ } else {
259
+ console.log(formatWorkflowSkillDraft(draft));
260
+ }
261
+ return;
262
+ }
263
+
190
264
  // Default: discover and display
191
265
  if (values.json || !process.stdout.isTTY) {
192
266
  console.log(JSON.stringify(report, null, 2));
@@ -1,4 +1,4 @@
1
- import type { PushPayloadV2 } from "../src/schemas.js";
1
+ import type { PushPayloadV2 } from "../src/types.js";
2
2
 
3
3
  /**
4
4
  * A valid PushPayloadV2 with at least one of every record type.
@@ -1,4 +1,4 @@
1
- import type { PushPayloadV2 } from "../src/schemas.js";
1
+ import type { PushPayloadV2 } from "../src/types.js";
2
2
 
3
3
  /**
4
4
  * A valid PushPayloadV2 with only evolution_evidence entries and
@@ -1,4 +1,4 @@
1
- import type { PushPayloadV2 } from "../src/schemas.js";
1
+ import type { PushPayloadV2 } from "../src/types.js";
2
2
 
3
3
  /**
4
4
  * A valid PushPayloadV2 with zero sessions but non-empty evolution_evidence.
@@ -1,4 +1,4 @@
1
- import type { PushPayloadV2 } from "../src/schemas.js";
1
+ import type { PushPayloadV2 } from "../src/types.js";
2
2
 
3
3
  /**
4
4
  * A valid PushPayloadV2 with invocations and prompts that reference a
@@ -140,10 +140,13 @@ export const CanonicalEvolutionEvidenceRecordSchema = z.object({
140
140
  evidence_id: z.string().min(1),
141
141
  skill_name: z.string().min(1),
142
142
  proposal_id: z.string().optional(),
143
+ timestamp: z.string().datetime().optional(),
144
+ skill_path: z.string().optional(),
143
145
  target: z.string().min(1),
144
146
  stage: z.string().min(1),
145
147
  rationale: z.string().optional(),
146
148
  confidence: z.number().min(0).max(1).optional(),
149
+ details: z.string().optional(),
147
150
  original_text: z.string().optional(),
148
151
  proposed_text: z.string().optional(),
149
152
  eval_set_json: z.unknown().optional(),
@@ -151,6 +154,37 @@ export const CanonicalEvolutionEvidenceRecordSchema = z.object({
151
154
  raw_source_ref: rawSourceRefSchema.optional(),
152
155
  });
153
156
 
157
+ export const CanonicalGradingResultRecordSchema = z.object({
158
+ grading_id: z.string().min(1),
159
+ session_id: z.string().min(1),
160
+ skill_name: z.string().min(1),
161
+ transcript_path: z.string().nullable().optional(),
162
+ graded_at: z.string().min(1),
163
+ pass_rate: z.number().min(0).max(1).nullable().optional(),
164
+ mean_score: z.number().min(0).max(1).nullable().optional(),
165
+ score_std_dev: z.number().nullable().optional(),
166
+ passed_count: z.number().int().nonnegative().nullable().optional(),
167
+ failed_count: z.number().int().nonnegative().nullable().optional(),
168
+ total_count: z.number().int().nonnegative().nullable().optional(),
169
+ expectations_json: z.string().nullable().optional(),
170
+ claims_json: z.string().nullable().optional(),
171
+ eval_feedback_json: z.string().nullable().optional(),
172
+ failure_feedback_json: z.string().nullable().optional(),
173
+ execution_metrics_json: z.string().nullable().optional(),
174
+ });
175
+
176
+ export const CanonicalImprovementSignalRecordSchema = z.object({
177
+ signal_id: z.string().min(1),
178
+ timestamp: z.string().min(1),
179
+ session_id: z.string().min(1),
180
+ query: z.string().min(1),
181
+ signal_type: z.string().min(1),
182
+ mentioned_skill: z.string().nullable().optional(),
183
+ consumed: z.boolean(),
184
+ consumed_at: z.string().nullable().optional(),
185
+ consumed_by_run: z.string().nullable().optional(),
186
+ });
187
+
154
188
  // ---------- Orchestrate run schemas ----------
155
189
 
156
190
  export const OrchestrateRunSkillActionSchema = z.object({
@@ -194,12 +228,14 @@ export const PushPayloadV2Schema = z.object({
194
228
  normalization_runs: z.array(CanonicalNormalizationRunRecordSchema).min(0),
195
229
  evolution_evidence: z.array(CanonicalEvolutionEvidenceRecordSchema).optional(),
196
230
  orchestrate_runs: z.array(PushOrchestrateRunRecordSchema).optional(),
231
+ grading_results: z.array(CanonicalGradingResultRecordSchema).optional(),
232
+ improvement_signals: z.array(CanonicalImprovementSignalRecordSchema).optional(),
197
233
  }),
198
234
  });
199
235
 
200
236
  // ---------- Inferred types from Zod schemas ----------
201
237
 
202
- export type PushPayloadV2 = z.infer<typeof PushPayloadV2Schema>;
238
+ export type ZodPushPayloadV2 = z.infer<typeof PushPayloadV2Schema>;
203
239
  export type ZodCanonicalSessionRecord = z.infer<typeof CanonicalSessionRecordSchema>;
204
240
  export type ZodCanonicalPromptRecord = z.infer<typeof CanonicalPromptRecordSchema>;
205
241
  export type ZodCanonicalSkillInvocationRecord = z.infer<
@@ -212,4 +248,8 @@ export type ZodCanonicalNormalizationRunRecord = z.infer<
212
248
  export type ZodCanonicalEvolutionEvidenceRecord = z.infer<
213
249
  typeof CanonicalEvolutionEvidenceRecordSchema
214
250
  >;
251
+ export type ZodCanonicalGradingResultRecord = z.infer<typeof CanonicalGradingResultRecordSchema>;
252
+ export type ZodCanonicalImprovementSignalRecord = z.infer<
253
+ typeof CanonicalImprovementSignalRecordSchema
254
+ >;
215
255
  export type ZodPushOrchestrateRunRecord = z.infer<typeof PushOrchestrateRunRecordSchema>;
@@ -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;
@@ -143,6 +143,16 @@ export interface CanonicalExecutionFactRecord extends CanonicalSessionRecordBase
143
143
  errors_encountered: number;
144
144
  input_tokens?: number;
145
145
  output_tokens?: number;
146
+ cached_input_tokens?: number;
147
+ reasoning_output_tokens?: number;
148
+ cost_usd?: number;
149
+ files_changed?: number;
150
+ lines_added?: number;
151
+ lines_removed?: number;
152
+ lines_modified?: number;
153
+ artifact_count?: number;
154
+ session_type?: string;
155
+ agent_summary?: string;
146
156
  duration_ms?: number;
147
157
  completion_status?: CanonicalCompletionStatus;
148
158
  end_reason?: string;
@@ -157,9 +167,100 @@ export interface CanonicalNormalizationRunRecord extends CanonicalRecordBase {
157
167
  repair_applied: boolean;
158
168
  }
159
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
+
160
219
  export type CanonicalRecord =
161
220
  | CanonicalSessionRecord
162
221
  | CanonicalPromptRecord
163
222
  | CanonicalSkillInvocationRecord
164
223
  | CanonicalExecutionFactRecord
165
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
+ }
package/package.json CHANGED
@@ -1,24 +1,35 @@
1
1
  {
2
2
  "name": "selftune",
3
- "version": "0.2.23",
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
+ }