selftune 0.2.31 → 0.2.32

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 (95) hide show
  1. package/README.md +83 -56
  2. package/apps/local-dashboard/dist/assets/index-B-ut4w0B.js +15 -0
  3. package/apps/local-dashboard/dist/assets/index-BFGfCVrL.css +1 -0
  4. package/apps/local-dashboard/dist/assets/vendor-ui-DfowE3Hu.js +1 -0
  5. package/apps/local-dashboard/dist/index.html +3 -3
  6. package/cli/selftune/command-surface.ts +613 -2
  7. package/cli/selftune/create/baseline.ts +429 -0
  8. package/cli/selftune/create/check.ts +35 -0
  9. package/cli/selftune/create/init.ts +115 -0
  10. package/cli/selftune/create/package-candidate-state.ts +771 -0
  11. package/cli/selftune/create/package-evaluator.ts +710 -0
  12. package/cli/selftune/create/package-fingerprint.ts +142 -0
  13. package/cli/selftune/create/package-search.ts +377 -0
  14. package/cli/selftune/create/publish.ts +431 -0
  15. package/cli/selftune/create/readiness.ts +495 -0
  16. package/cli/selftune/create/replay.ts +330 -0
  17. package/cli/selftune/create/report.ts +74 -0
  18. package/cli/selftune/create/scaffold.ts +121 -0
  19. package/cli/selftune/create/skills-ref-adapter.ts +177 -0
  20. package/cli/selftune/create/status.ts +33 -0
  21. package/cli/selftune/create/templates.ts +249 -0
  22. package/cli/selftune/cron/setup.ts +1 -1
  23. package/cli/selftune/dashboard-action-events.ts +4 -1
  24. package/cli/selftune/dashboard-action-result.ts +789 -24
  25. package/cli/selftune/dashboard-action-stream.ts +80 -0
  26. package/cli/selftune/dashboard-contract.ts +146 -3
  27. package/cli/selftune/dashboard-server.ts +5 -4
  28. package/cli/selftune/eval/hooks-to-evals.ts +58 -35
  29. package/cli/selftune/eval/synthetic-evals.ts +145 -17
  30. package/cli/selftune/evolution/bounded-mutations.ts +1045 -0
  31. package/cli/selftune/evolution/evolve-body.ts +9 -36
  32. package/cli/selftune/evolution/evolve.ts +8 -72
  33. package/cli/selftune/evolution/stopping-criteria.ts +5 -13
  34. package/cli/selftune/evolution/unblock-suggestions.ts +0 -16
  35. package/cli/selftune/evolution/validate-host-replay.ts +115 -15
  36. package/cli/selftune/improve.ts +206 -0
  37. package/cli/selftune/index.ts +123 -6
  38. package/cli/selftune/init.ts +1 -1
  39. package/cli/selftune/localdb/queries/dashboard.ts +30 -0
  40. package/cli/selftune/localdb/schema.ts +52 -0
  41. package/cli/selftune/monitoring/watch.ts +257 -23
  42. package/cli/selftune/orchestrate/execute.ts +300 -1
  43. package/cli/selftune/orchestrate/finalize.ts +14 -0
  44. package/cli/selftune/orchestrate/plan.ts +22 -5
  45. package/cli/selftune/orchestrate/prepare.ts +59 -4
  46. package/cli/selftune/orchestrate/report.ts +1 -1
  47. package/cli/selftune/orchestrate.ts +34 -1
  48. package/cli/selftune/publish.ts +35 -0
  49. package/cli/selftune/routes/actions.ts +81 -15
  50. package/cli/selftune/routes/overview.ts +1 -1
  51. package/cli/selftune/routes/skill-report.ts +147 -2
  52. package/cli/selftune/run.ts +18 -0
  53. package/cli/selftune/schedule.ts +3 -3
  54. package/cli/selftune/search-run.ts +703 -0
  55. package/cli/selftune/status.ts +35 -11
  56. package/cli/selftune/testing-readiness.ts +431 -40
  57. package/cli/selftune/types.ts +316 -0
  58. package/cli/selftune/utils/eval-readiness.ts +1 -0
  59. package/cli/selftune/utils/json-output.ts +11 -0
  60. package/cli/selftune/utils/lifecycle-surface.ts +48 -0
  61. package/cli/selftune/utils/query-filter.ts +82 -1
  62. package/cli/selftune/utils/tui.ts +85 -2
  63. package/cli/selftune/verify.ts +205 -0
  64. package/cli/selftune/workflows/proposals.ts +1 -1
  65. package/cli/selftune/workflows/skill-scaffold.ts +141 -63
  66. package/cli/selftune/workflows/workflows.ts +4 -4
  67. package/package.json +1 -1
  68. package/skill/SKILL.md +148 -85
  69. package/skill/references/cli-quick-reference.md +16 -1
  70. package/skill/references/creator-playbook.md +31 -10
  71. package/skill/workflows/Baseline.md +8 -9
  72. package/skill/workflows/Contributions.md +4 -4
  73. package/skill/workflows/Create.md +173 -0
  74. package/skill/workflows/CreateTestDeploy.md +34 -30
  75. package/skill/workflows/Cron.md +2 -2
  76. package/skill/workflows/Dashboard.md +3 -3
  77. package/skill/workflows/Evals.md +13 -7
  78. package/skill/workflows/Evolve.md +75 -32
  79. package/skill/workflows/EvolveBody.md +22 -15
  80. package/skill/workflows/Hook.md +1 -1
  81. package/skill/workflows/Improve.md +168 -0
  82. package/skill/workflows/Initialize.md +3 -3
  83. package/skill/workflows/Orchestrate.md +49 -12
  84. package/skill/workflows/Publish.md +100 -0
  85. package/skill/workflows/Run.md +72 -0
  86. package/skill/workflows/Schedule.md +2 -2
  87. package/skill/workflows/SearchRun.md +89 -0
  88. package/skill/workflows/SignalsDashboard.md +2 -2
  89. package/skill/workflows/UnitTest.md +13 -4
  90. package/skill/workflows/Verify.md +136 -0
  91. package/skill/workflows/Watch.md +114 -47
  92. package/skill/workflows/Workflows.md +13 -8
  93. package/apps/local-dashboard/dist/assets/index-B7v_o1WC.js +0 -15
  94. package/apps/local-dashboard/dist/assets/index-CrO77SVi.css +0 -1
  95. package/apps/local-dashboard/dist/assets/vendor-ui-B0H8s1mP.js +0 -1
@@ -9,6 +9,12 @@
9
9
  import type { Database } from "bun:sqlite";
10
10
 
11
11
  import { parseCursorParam } from "../dashboard-contract.js";
12
+ import {
13
+ listAcceptedPackageFrontierCandidates,
14
+ listPackageCandidates,
15
+ } from "../create/package-candidate-state.js";
16
+ import { readSearchRuns } from "../create/package-search.js";
17
+ import { computeCreateDashboardReadiness, isCreateSkillDraft } from "../create/readiness.js";
12
18
  import { scoreDescription } from "../evolution/description-quality.js";
13
19
  import {
14
20
  getExecutionMetrics,
@@ -17,7 +23,129 @@ import {
17
23
  getSkillReportPayload,
18
24
  safeParseJson,
19
25
  } from "../localdb/queries.js";
20
- import { getSkillTestingReadiness } from "../testing-readiness.js";
26
+ import { computeWatchTrustScore } from "../monitoring/watch.js";
27
+ import type { WatchResult } from "../monitoring/watch.js";
28
+ import {
29
+ getSkillTestingReadiness,
30
+ readCanonicalPackageEvaluationArtifact,
31
+ } from "../testing-readiness.js";
32
+ import type { CreatePackageEvaluationWatchSummary } from "../types.js";
33
+
34
+ function readMeasuredDelta(summary: {
35
+ candidate_acceptance?: {
36
+ replay_pass_rate_delta: number | null;
37
+ routing_pass_rate_delta: number | null;
38
+ baseline_lift_delta: number | null;
39
+ body_quality_delta: number | null;
40
+ unit_test_pass_rate_delta: number | null;
41
+ };
42
+ }): number | null {
43
+ const acceptance = summary.candidate_acceptance;
44
+ if (!acceptance) return null;
45
+
46
+ const deltas = [
47
+ acceptance.replay_pass_rate_delta,
48
+ acceptance.routing_pass_rate_delta,
49
+ acceptance.baseline_lift_delta,
50
+ acceptance.body_quality_delta,
51
+ acceptance.unit_test_pass_rate_delta,
52
+ ];
53
+ return deltas.find((delta) => delta != null) ?? null;
54
+ }
55
+
56
+ function isWatchDemoted(summary: {
57
+ watch?: {
58
+ rolled_back?: boolean | null;
59
+ alert?: string | null;
60
+ grade_regression?: boolean | null;
61
+ efficiency_regression?: boolean | null;
62
+ };
63
+ }): boolean {
64
+ const watch = summary.watch;
65
+ return Boolean(
66
+ watch?.rolled_back || watch?.alert || watch?.grade_regression || watch?.efficiency_regression,
67
+ );
68
+ }
69
+
70
+ function buildFrontierState(db: Database, skillName: string) {
71
+ const candidates = listPackageCandidates(skillName, db);
72
+ if (candidates.length === 0) return null;
73
+
74
+ const acceptedFrontier = listAcceptedPackageFrontierCandidates(skillName, db);
75
+ const evidenceRanks = new Map(
76
+ acceptedFrontier.map((candidate, index) => [candidate.candidate_id, index + 1]),
77
+ );
78
+
79
+ const members = candidates.map((candidate) => ({
80
+ candidate_id: candidate.candidate_id,
81
+ skill_name: candidate.skill_name,
82
+ fingerprint: candidate.package_fingerprint,
83
+ decision:
84
+ candidate.latest_acceptance_decision === "root" ||
85
+ candidate.latest_acceptance_decision === "accepted"
86
+ ? "accepted"
87
+ : candidate.latest_acceptance_decision === "rejected"
88
+ ? "rejected"
89
+ : "pending",
90
+ measured_delta: readMeasuredDelta(candidate.summary),
91
+ created_at: candidate.first_evaluated_at,
92
+ parent_candidate_id: candidate.parent_candidate_id,
93
+ watch_demoted: isWatchDemoted(candidate.summary),
94
+ evidence_rank: evidenceRanks.get(candidate.candidate_id) ?? null,
95
+ }));
96
+
97
+ const latestSearchRun = readSearchRuns(db, skillName)[0] ?? null;
98
+
99
+ return {
100
+ skill_name: skillName,
101
+ accepted_count: members.filter((member) => member.decision === "accepted").length,
102
+ rejected_count: members.filter((member) => member.decision === "rejected").length,
103
+ pending_count: members.filter((member) => member.decision === "pending").length,
104
+ members,
105
+ latest_search_run: latestSearchRun,
106
+ };
107
+ }
108
+
109
+ function hydrateWatchResult(summary: CreatePackageEvaluationWatchSummary): WatchResult {
110
+ return {
111
+ snapshot: summary.snapshot,
112
+ alert: summary.alert,
113
+ rolledBack: summary.rolled_back,
114
+ recommendation: summary.recommendation,
115
+ recommended_command: summary.recommended_command,
116
+ gradeAlert: summary.grade_alert,
117
+ gradeRegression: summary.grade_regression,
118
+ ...(summary.efficiency_alert || summary.efficiency_regression
119
+ ? {
120
+ efficiencyAlert: summary.efficiency_alert ?? null,
121
+ efficiencyRegression: summary.efficiency_regression ?? null,
122
+ }
123
+ : {}),
124
+ };
125
+ }
126
+
127
+ function readWatchTrustScore(db: Database, skillName: string): number | null {
128
+ const row = db
129
+ .query(
130
+ `SELECT summary_json
131
+ FROM package_evaluation_reports
132
+ WHERE skill_name = ?`,
133
+ )
134
+ .get(skillName) as { summary_json: string } | null;
135
+
136
+ const parsedSummary = row?.summary_json ? safeParseJson(row.summary_json) : null;
137
+ const summaryWatch = parsedSummary?.watch as CreatePackageEvaluationWatchSummary | undefined;
138
+ if (summaryWatch?.snapshot) {
139
+ return computeWatchTrustScore(hydrateWatchResult(summaryWatch));
140
+ }
141
+
142
+ const artifactWatch = readCanonicalPackageEvaluationArtifact(skillName)?.summary.watch;
143
+ if (artifactWatch?.snapshot) {
144
+ return computeWatchTrustScore(hydrateWatchResult(artifactWatch));
145
+ }
146
+
147
+ return null;
148
+ }
21
149
 
22
150
  export function handleSkillReport(
23
151
  db: Database,
@@ -26,6 +154,18 @@ export function handleSkillReport(
26
154
  ): Response {
27
155
  const report = getSkillReportPayload(db, skillName);
28
156
  const testing_readiness = getSkillTestingReadiness(db, skillName);
157
+ const frontier_state = buildFrontierState(db, skillName);
158
+ const watch_trust_score = readWatchTrustScore(db, skillName);
159
+ let create_readiness = null;
160
+ if (testing_readiness?.skill_path && isCreateSkillDraft(testing_readiness.skill_path)) {
161
+ try {
162
+ create_readiness = computeCreateDashboardReadiness(testing_readiness.skill_path, {
163
+ getTestingReadiness: () => testing_readiness,
164
+ });
165
+ } catch {
166
+ create_readiness = null;
167
+ }
168
+ }
29
169
 
30
170
  // 1. Evolution audit with eval_snapshot
31
171
  const evolution = db
@@ -187,7 +327,9 @@ export function handleSkillReport(
187
327
  testing_readiness?.unit_test_cases ||
188
328
  testing_readiness?.replay_check_count ||
189
329
  testing_readiness?.baseline_sample_size,
190
- );
330
+ ) ||
331
+ Boolean(create_readiness) ||
332
+ Boolean(frontier_state);
191
333
  if (!hasData) {
192
334
  return Response.json({ error: "Skill not found" }, { status: 404 });
193
335
  }
@@ -892,5 +1034,8 @@ export function handleSkillReport(
892
1034
  data_hygiene,
893
1035
  examples,
894
1036
  testing_readiness,
1037
+ create_readiness,
1038
+ watch_trust_score,
1039
+ frontier_state,
895
1040
  });
896
1041
  }
@@ -0,0 +1,18 @@
1
+ import { PUBLIC_COMMAND_SURFACES, renderCommandHelp } from "./command-surface.js";
2
+ import { cliMain as orchestrateCliMain } from "./orchestrate.js";
3
+ import { handleCLIError } from "./utils/cli-error.js";
4
+
5
+ export async function cliMain(): Promise<void> {
6
+ const rawArgs = process.argv.slice(2);
7
+
8
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
9
+ console.log(renderCommandHelp(PUBLIC_COMMAND_SURFACES.run));
10
+ process.exit(0);
11
+ }
12
+
13
+ await orchestrateCliMain();
14
+ }
15
+
16
+ if (import.meta.main) {
17
+ cliMain().catch(handleCLIError);
18
+ }
@@ -58,7 +58,7 @@ function commandForJob(jobName: string): string {
58
58
  case "selftune-status":
59
59
  return "selftune sync && selftune status";
60
60
  case "selftune-orchestrate":
61
- return "selftune orchestrate --max-skills 3";
61
+ return "selftune run --max-skills 3";
62
62
  default:
63
63
  return `selftune ${jobName.replace("selftune-", "")}`;
64
64
  }
@@ -162,8 +162,8 @@ export function generateCrontab(): string {
162
162
  const lines = [
163
163
  "# selftune automation — add to your crontab with: crontab -e",
164
164
  "#",
165
- "# The core loop: sync → orchestrate",
166
- "# status remains a reporting job; orchestrate handles sync, candidate",
165
+ "# The core loop: sync → run",
166
+ "# status remains a reporting job; run handles sync, candidate",
167
167
  "# selection, low-risk description evolution, and watch/rollback follow-up.",
168
168
  "#",
169
169
  `PATH=${home}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`,