selftune 0.2.18 → 0.2.19

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 (65) hide show
  1. package/README.md +9 -4
  2. package/apps/local-dashboard/dist/assets/index-DnhnXQm6.js +60 -0
  3. package/apps/local-dashboard/dist/assets/index-_EcLywDg.css +1 -0
  4. package/apps/local-dashboard/dist/assets/vendor-table-BIiI3YhS.js +1 -0
  5. package/apps/local-dashboard/dist/assets/vendor-ui-CGEmUayx.js +12 -0
  6. package/apps/local-dashboard/dist/index.html +5 -5
  7. package/cli/selftune/alpha-upload/stage-canonical.ts +7 -6
  8. package/cli/selftune/constants.ts +10 -0
  9. package/cli/selftune/contribute/contribute.ts +30 -2
  10. package/cli/selftune/contribution-config.ts +249 -0
  11. package/cli/selftune/contribution-relay.ts +177 -0
  12. package/cli/selftune/contribution-signals.ts +219 -0
  13. package/cli/selftune/contribution-staging.ts +147 -0
  14. package/cli/selftune/contributions.ts +532 -0
  15. package/cli/selftune/creator-contributions.ts +333 -0
  16. package/cli/selftune/dashboard-contract.ts +205 -1
  17. package/cli/selftune/dashboard-server.ts +45 -11
  18. package/cli/selftune/eval/family-overlap.ts +395 -0
  19. package/cli/selftune/eval/hooks-to-evals.ts +182 -28
  20. package/cli/selftune/eval/synthetic-evals.ts +298 -11
  21. package/cli/selftune/export.ts +2 -2
  22. package/cli/selftune/index.ts +41 -5
  23. package/cli/selftune/ingestors/codex-rollout.ts +31 -35
  24. package/cli/selftune/ingestors/codex-wrapper.ts +32 -24
  25. package/cli/selftune/localdb/db.ts +2 -2
  26. package/cli/selftune/localdb/queries.ts +701 -30
  27. package/cli/selftune/localdb/schema.ts +20 -0
  28. package/cli/selftune/recover.ts +153 -0
  29. package/cli/selftune/repair/skill-usage.ts +363 -4
  30. package/cli/selftune/routes/actions.ts +35 -1
  31. package/cli/selftune/routes/analytics.ts +14 -0
  32. package/cli/selftune/routes/index.ts +1 -0
  33. package/cli/selftune/routes/overview.ts +112 -4
  34. package/cli/selftune/routes/skill-report.ts +569 -10
  35. package/cli/selftune/status.ts +81 -2
  36. package/cli/selftune/sync.ts +56 -2
  37. package/cli/selftune/trust-model.ts +66 -0
  38. package/cli/selftune/types.ts +49 -0
  39. package/cli/selftune/utils/skill-detection.ts +43 -0
  40. package/cli/selftune/watchlist.ts +65 -0
  41. package/package.json +1 -1
  42. package/packages/ui/src/components/ActivityTimeline.tsx +165 -150
  43. package/packages/ui/src/components/EvidenceViewer.tsx +335 -144
  44. package/packages/ui/src/components/EvolutionTimeline.tsx +58 -28
  45. package/packages/ui/src/components/OrchestrateRunsPanel.tsx +33 -16
  46. package/packages/ui/src/components/RecentActivityFeed.tsx +72 -41
  47. package/packages/ui/src/components/section-cards.tsx +12 -9
  48. package/packages/ui/src/primitives/card.tsx +1 -1
  49. package/skill/SKILL.md +11 -1
  50. package/skill/Workflows/AlphaUpload.md +4 -0
  51. package/skill/Workflows/Composability.md +64 -0
  52. package/skill/Workflows/Contribute.md +6 -3
  53. package/skill/Workflows/Contributions.md +97 -0
  54. package/skill/Workflows/CreatorContributions.md +74 -0
  55. package/skill/Workflows/Dashboard.md +31 -0
  56. package/skill/Workflows/Evals.md +57 -8
  57. package/skill/Workflows/Ingest.md +7 -0
  58. package/skill/Workflows/Initialize.md +20 -1
  59. package/skill/Workflows/Recover.md +84 -0
  60. package/skill/Workflows/RepairSkillUsage.md +12 -4
  61. package/skill/Workflows/Sync.md +18 -12
  62. package/apps/local-dashboard/dist/assets/index-BMIS6uUh.css +0 -2
  63. package/apps/local-dashboard/dist/assets/index-DOu3iLD9.js +0 -16
  64. package/apps/local-dashboard/dist/assets/vendor-table-pHbDxq36.js +0 -8
  65. package/apps/local-dashboard/dist/assets/vendor-ui-DIwlrGlb.js +0 -12
@@ -41,11 +41,13 @@ import type {
41
41
  SessionTelemetryRecord,
42
42
  SkillUsageRecord,
43
43
  } from "../types.js";
44
+ import { extractActionableQueryText } from "../utils/query-filter.js";
45
+ import { getInternalPromptTargetSkill, isWrappedNonUserPart } from "../utils/skill-detection.js";
44
46
  import {
45
47
  classifySkillPath,
46
- containsWholeSkillMention,
47
48
  extractExplicitSkillMentions,
48
49
  extractSkillNamesFromInstructions,
50
+ extractSkillNamesFromPathReferences,
49
51
  findInstalledSkillNames,
50
52
  findInstalledSkillPath,
51
53
  findRepositorySkillDirs,
@@ -112,26 +114,34 @@ export function parseJsonlStream(lines: string[], skillNames: Set<string>): Pars
112
114
  let outputTokens = 0;
113
115
  const agentMessages: string[] = [];
114
116
  const sessionSkillNames = new Set(skillNames);
117
+ const markSkillTriggered = (skillName: string): void => {
118
+ if (!skillsTriggered.includes(skillName)) {
119
+ skillsTriggered.push(skillName);
120
+ }
121
+ };
115
122
  const rememberSessionSkillNames = (text: unknown): void => {
116
123
  if (typeof text !== "string" || !text) return;
117
124
  for (const skillName of extractSkillNamesFromInstructions(text, sessionSkillNames)) {
118
125
  sessionSkillNames.add(skillName);
119
126
  }
120
127
  };
121
- const detectTriggeredSkills = (text: unknown): void => {
128
+ const detectExplicitSkillReads = (text: unknown): void => {
122
129
  if (typeof text !== "string" || !text) return;
123
- for (const skillName of sessionSkillNames) {
124
- if (containsWholeSkillMention(text, skillName) && !skillsTriggered.includes(skillName)) {
125
- skillsTriggered.push(skillName);
126
- }
130
+ for (const skillName of extractSkillNamesFromPathReferences(text, sessionSkillNames)) {
131
+ markSkillTriggered(skillName);
127
132
  }
128
133
  };
129
134
  const detectExplicitPromptSkillMentions = (text: unknown): void => {
130
135
  if (typeof text !== "string" || !text) return;
131
- for (const skillName of extractExplicitSkillMentions(text, sessionSkillNames)) {
132
- if (!skillsTriggered.includes(skillName)) {
133
- skillsTriggered.push(skillName);
134
- }
136
+ if (isWrappedNonUserPart(text)) return;
137
+ const actionableText = extractActionableQueryText(text) ?? text;
138
+ const internalTargetSkill = getInternalPromptTargetSkill(actionableText, sessionSkillNames);
139
+ if (internalTargetSkill) {
140
+ markSkillTriggered(internalTargetSkill);
141
+ return;
142
+ }
143
+ for (const skillName of extractExplicitSkillMentions(actionableText, sessionSkillNames)) {
144
+ markSkillTriggered(skillName);
135
145
  }
136
146
  };
137
147
 
@@ -187,40 +197,38 @@ export function parseJsonlStream(lines: string[], skillNames: Set<string>): Pars
187
197
  } else if (itemType === "agent_message") {
188
198
  const text = (item.text as string) ?? "";
189
199
  if (text) agentMessages.push(text.slice(0, 500));
190
- detectTriggeredSkills(text);
191
200
  } else if (itemType === "reasoning") {
192
201
  toolCalls.reasoning = (toolCalls.reasoning ?? 0) + 1;
193
202
  }
194
203
  }
195
204
 
196
- // Detect skill names in text on completed events (whole-word match)
197
- const textContent = ((item.text as string) ?? "") + ((item.command as string) ?? "");
198
- if (etype === "item.completed") {
199
- detectTriggeredSkills(textContent);
205
+ if (etype === "item.completed" && itemType === "command_execution") {
206
+ detectExplicitSkillReads(item.command);
200
207
  }
201
208
  } else if (etype === "response_item") {
202
209
  const payload = (event.payload as Record<string, unknown>) ?? {};
203
210
  const itemType = (payload.type as string) ?? "";
204
211
  if (itemType === "function_call") {
205
- detectTriggeredSkills(payload.arguments);
212
+ detectExplicitSkillReads(payload.arguments);
206
213
  } else if (itemType === "message") {
207
- const content = Array.isArray(payload.content)
214
+ const parts = Array.isArray(payload.content)
208
215
  ? payload.content
209
216
  .map((part) =>
210
217
  typeof part === "object" && part
211
218
  ? (((part as Record<string, unknown>).text as string | undefined) ?? "")
212
219
  : "",
213
220
  )
214
- .join("\n")
215
- : "";
221
+ .filter(Boolean)
222
+ : [];
223
+ const content = parts.join("\n");
216
224
  rememberSessionSkillNames(content);
217
- if ((payload.role as string) === "assistant") {
218
- detectTriggeredSkills(content);
219
- } else if ((payload.role as string) === "user") {
220
- detectExplicitPromptSkillMentions(content);
225
+ if ((payload.role as string) === "user") {
226
+ for (const part of parts) {
227
+ detectExplicitPromptSkillMentions(part);
228
+ }
221
229
  }
222
230
  } else if (itemType === "agent_reasoning") {
223
- detectTriggeredSkills(payload.text);
231
+ detectExplicitSkillReads(payload.text);
224
232
  }
225
233
  } else if (etype === "error") {
226
234
  errors += 1;
@@ -54,7 +54,7 @@ export function openDb(dbPath: string = DB_PATH): Database {
54
54
  const msg = err instanceof Error ? err.message : String(err);
55
55
  if (msg.includes("duplicate column")) continue; // expected on subsequent runs
56
56
  throw new Error(
57
- `Schema migration failed: ${msg}. Export first with 'selftune export', then remove '${dbPath}' and rerun 'selftune sync --force' or 'selftune dashboard'.`,
57
+ `Schema migration failed: ${msg}. Export first with 'selftune export', then remove '${dbPath}' and rerun 'selftune sync --force'. If you need legacy/export JSONL backfill, run 'selftune recover --full --force'.`,
58
58
  );
59
59
  }
60
60
  }
@@ -67,7 +67,7 @@ export function openDb(dbPath: string = DB_PATH): Database {
67
67
  const msg = err instanceof Error ? err.message : String(err);
68
68
  if (msg.includes("already exists")) continue; // expected on subsequent runs
69
69
  throw new Error(
70
- `Schema index creation failed: ${msg}. Export first with 'selftune export', then remove '${dbPath}' and rerun 'selftune sync --force' or 'selftune dashboard'.`,
70
+ `Schema index creation failed: ${msg}. Export first with 'selftune export', then remove '${dbPath}' and rerun 'selftune sync --force'. If you need legacy/export JSONL backfill, run 'selftune recover --full --force'.`,
71
71
  );
72
72
  }
73
73
  }