selftune 0.2.0 → 0.2.2
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.
- package/.claude/agents/diagnosis-analyst.md +20 -10
- package/.claude/agents/evolution-reviewer.md +14 -1
- package/.claude/agents/integration-guide.md +18 -6
- package/.claude/agents/pattern-analyst.md +18 -5
- package/CHANGELOG.md +12 -4
- package/README.md +43 -35
- package/apps/local-dashboard/dist/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/apps/local-dashboard/dist/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/apps/local-dashboard/dist/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/apps/local-dashboard/dist/assets/index-C4EOTFZ2.js +15 -0
- package/apps/local-dashboard/dist/assets/index-bl-Webyd.css +1 -0
- package/apps/local-dashboard/dist/assets/vendor-react-U7zYD9Rg.js +60 -0
- package/apps/local-dashboard/dist/assets/vendor-table-B7VF2Ipl.js +26 -0
- package/apps/local-dashboard/dist/assets/vendor-ui-D7_zX_qy.js +346 -0
- package/apps/local-dashboard/dist/favicon.png +0 -0
- package/apps/local-dashboard/dist/index.html +17 -0
- package/apps/local-dashboard/dist/logo.png +0 -0
- package/apps/local-dashboard/dist/logo.svg +9 -0
- package/cli/selftune/badge/badge-data.ts +1 -1
- package/cli/selftune/badge/badge.ts +4 -8
- package/cli/selftune/canonical-export.ts +183 -0
- package/cli/selftune/constants.ts +28 -0
- package/cli/selftune/contribute/contribute.ts +1 -1
- package/cli/selftune/cron/setup.ts +17 -17
- package/cli/selftune/dashboard-contract.ts +202 -0
- package/cli/selftune/dashboard-server.ts +653 -186
- package/cli/selftune/dashboard.ts +41 -176
- package/cli/selftune/eval/baseline.ts +5 -4
- package/cli/selftune/eval/composability-v2.ts +273 -0
- package/cli/selftune/eval/hooks-to-evals.ts +34 -15
- package/cli/selftune/eval/unit-test-cli.ts +1 -1
- package/cli/selftune/evolution/evidence.ts +26 -0
- package/cli/selftune/evolution/evolve-body.ts +105 -11
- package/cli/selftune/evolution/evolve.ts +371 -25
- package/cli/selftune/evolution/extract-patterns.ts +87 -29
- package/cli/selftune/evolution/rollback.ts +2 -2
- package/cli/selftune/grading/auto-grade.ts +200 -0
- package/cli/selftune/grading/grade-session.ts +448 -97
- package/cli/selftune/grading/results.ts +42 -0
- package/cli/selftune/hooks/prompt-log.ts +172 -2
- package/cli/selftune/hooks/session-stop.ts +123 -3
- package/cli/selftune/hooks/skill-eval.ts +119 -3
- package/cli/selftune/index.ts +395 -116
- package/cli/selftune/ingestors/claude-replay.ts +140 -114
- package/cli/selftune/ingestors/codex-rollout.ts +345 -46
- package/cli/selftune/ingestors/codex-wrapper.ts +207 -39
- package/cli/selftune/ingestors/openclaw-ingest.ts +141 -8
- package/cli/selftune/ingestors/opencode-ingest.ts +193 -17
- package/cli/selftune/init.ts +227 -14
- package/cli/selftune/last.ts +14 -5
- package/cli/selftune/localdb/db.ts +63 -0
- package/cli/selftune/localdb/materialize.ts +428 -0
- package/cli/selftune/localdb/queries.ts +376 -0
- package/cli/selftune/localdb/schema.ts +204 -0
- package/cli/selftune/monitoring/watch.ts +66 -15
- package/cli/selftune/normalization.ts +682 -0
- package/cli/selftune/observability.ts +19 -44
- package/cli/selftune/orchestrate.ts +1073 -0
- package/cli/selftune/quickstart.ts +203 -0
- package/cli/selftune/repair/skill-usage.ts +576 -0
- package/cli/selftune/schedule.ts +561 -0
- package/cli/selftune/status.ts +48 -26
- package/cli/selftune/sync.ts +627 -0
- package/cli/selftune/types.ts +148 -0
- package/cli/selftune/utils/canonical-log.ts +45 -0
- package/cli/selftune/utils/hooks.ts +41 -0
- package/cli/selftune/utils/html.ts +27 -0
- package/cli/selftune/utils/llm-call.ts +78 -20
- package/cli/selftune/utils/math.ts +10 -0
- package/cli/selftune/utils/query-filter.ts +139 -0
- package/cli/selftune/utils/skill-discovery.ts +340 -0
- package/cli/selftune/utils/skill-log.ts +68 -0
- package/cli/selftune/utils/skill-usage-confidence.ts +18 -0
- package/cli/selftune/utils/transcript.ts +272 -26
- package/cli/selftune/workflows/discover.ts +254 -0
- package/cli/selftune/workflows/skill-md-writer.ts +288 -0
- package/cli/selftune/workflows/workflows.ts +188 -0
- package/package.json +21 -8
- package/packages/telemetry-contract/README.md +11 -0
- package/packages/telemetry-contract/fixtures/golden.json +87 -0
- package/packages/telemetry-contract/fixtures/golden.test.ts +42 -0
- package/packages/telemetry-contract/index.ts +1 -0
- package/packages/telemetry-contract/package.json +19 -0
- package/packages/telemetry-contract/src/index.ts +2 -0
- package/packages/telemetry-contract/src/types.ts +163 -0
- package/packages/telemetry-contract/src/validators.ts +109 -0
- package/skill/SKILL.md +84 -53
- package/skill/Workflows/AutoActivation.md +17 -16
- package/skill/Workflows/Badge.md +6 -0
- package/skill/Workflows/Baseline.md +46 -23
- package/skill/Workflows/Composability.md +12 -5
- package/skill/Workflows/Contribute.md +17 -14
- package/skill/Workflows/Cron.md +56 -79
- package/skill/Workflows/Dashboard.md +45 -34
- package/skill/Workflows/Doctor.md +30 -17
- package/skill/Workflows/Evals.md +64 -40
- package/skill/Workflows/EvolutionMemory.md +2 -0
- package/skill/Workflows/Evolve.md +102 -47
- package/skill/Workflows/EvolveBody.md +6 -6
- package/skill/Workflows/Grade.md +36 -31
- package/skill/Workflows/ImportSkillsBench.md +11 -5
- package/skill/Workflows/Ingest.md +43 -36
- package/skill/Workflows/Initialize.md +44 -30
- package/skill/Workflows/Orchestrate.md +139 -0
- package/skill/Workflows/Replay.md +39 -18
- package/skill/Workflows/Rollback.md +3 -3
- package/skill/Workflows/Schedule.md +61 -0
- package/skill/Workflows/Sync.md +88 -0
- package/skill/Workflows/UnitTest.md +34 -22
- package/skill/Workflows/Watch.md +14 -4
- package/skill/Workflows/Workflows.md +129 -0
- package/skill/assets/activation-rules-default.json +26 -0
- package/skill/assets/multi-skill-settings.json +63 -0
- package/skill/assets/single-skill-settings.json +57 -0
- package/skill/references/invocation-taxonomy.md +2 -2
- package/skill/references/logs.md +164 -2
- package/skill/references/setup-patterns.md +65 -0
- package/skill/references/version-history.md +40 -0
- package/skill/settings_snippet.json +1 -1
- package/templates/multi-skill-settings.json +7 -7
- package/templates/single-skill-settings.json +6 -6
- package/dashboard/index.html +0 -1680
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* selftune quickstart — Guided onboarding that runs init, ingest, and status.
|
|
3
|
+
*
|
|
4
|
+
* Steps:
|
|
5
|
+
* 1. Run `init` if config doesn't exist
|
|
6
|
+
* 2. Run `ingest claude` if marker file doesn't exist
|
|
7
|
+
* 3. Run `status` to display current state
|
|
8
|
+
* 4. Suggest top 3 skills to evolve
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
CLAUDE_CODE_MARKER,
|
|
15
|
+
CLAUDE_CODE_PROJECTS_DIR,
|
|
16
|
+
EVOLUTION_AUDIT_LOG,
|
|
17
|
+
QUERY_LOG,
|
|
18
|
+
SELFTUNE_CONFIG_DIR,
|
|
19
|
+
SELFTUNE_CONFIG_PATH,
|
|
20
|
+
TELEMETRY_LOG,
|
|
21
|
+
} from "./constants.js";
|
|
22
|
+
import { findTranscriptFiles, parseSession, writeSession } from "./ingestors/claude-replay.js";
|
|
23
|
+
import { runInit } from "./init.js";
|
|
24
|
+
import { doctor } from "./observability.js";
|
|
25
|
+
import type { SkillStatus } from "./status.js";
|
|
26
|
+
import { computeStatus, formatStatus } from "./status.js";
|
|
27
|
+
import type { EvolutionAuditEntry, QueryLogRecord, SessionTelemetryRecord } from "./types.js";
|
|
28
|
+
import { loadMarker, readJsonl, saveMarker } from "./utils/jsonl.js";
|
|
29
|
+
import { readEffectiveSkillUsageRecords } from "./utils/skill-log.js";
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// quickstart logic
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
export async function quickstart(): Promise<void> {
|
|
36
|
+
console.log("selftune quickstart");
|
|
37
|
+
console.log("=".repeat(20));
|
|
38
|
+
console.log("");
|
|
39
|
+
|
|
40
|
+
// Step 1: Init if needed
|
|
41
|
+
if (existsSync(SELFTUNE_CONFIG_PATH)) {
|
|
42
|
+
console.log("[1/3] Config exists, skipping init.");
|
|
43
|
+
} else {
|
|
44
|
+
console.log("[1/3] Running init...");
|
|
45
|
+
try {
|
|
46
|
+
await runInit({
|
|
47
|
+
configDir: SELFTUNE_CONFIG_DIR,
|
|
48
|
+
configPath: SELFTUNE_CONFIG_PATH,
|
|
49
|
+
force: false,
|
|
50
|
+
});
|
|
51
|
+
console.log(" Config created.");
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
54
|
+
console.error(` Init failed: ${msg}`);
|
|
55
|
+
console.log(" You can run `selftune init` manually to troubleshoot.");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Step 2: Ingest if marker doesn't exist
|
|
60
|
+
if (existsSync(CLAUDE_CODE_MARKER)) {
|
|
61
|
+
console.log("[2/3] Ingest marker exists, skipping ingestion.");
|
|
62
|
+
} else {
|
|
63
|
+
console.log("[2/3] Running ingest claude...");
|
|
64
|
+
try {
|
|
65
|
+
const transcriptFiles = findTranscriptFiles(CLAUDE_CODE_PROJECTS_DIR);
|
|
66
|
+
if (transcriptFiles.length === 0) {
|
|
67
|
+
console.log(" No Claude Code transcripts found. Skipping.");
|
|
68
|
+
} else {
|
|
69
|
+
const alreadyIngested = loadMarker(CLAUDE_CODE_MARKER);
|
|
70
|
+
const newIngested = new Set<string>();
|
|
71
|
+
let ingestedCount = 0;
|
|
72
|
+
|
|
73
|
+
for (const transcriptFile of transcriptFiles) {
|
|
74
|
+
const session = parseSession(transcriptFile);
|
|
75
|
+
if (session === null) continue;
|
|
76
|
+
writeSession(session, false);
|
|
77
|
+
newIngested.add(transcriptFile);
|
|
78
|
+
ingestedCount++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (newIngested.size > 0) {
|
|
82
|
+
saveMarker(CLAUDE_CODE_MARKER, new Set([...alreadyIngested, ...newIngested]));
|
|
83
|
+
}
|
|
84
|
+
console.log(` Ingested ${ingestedCount} sessions.`);
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
88
|
+
console.error(` Ingest failed: ${msg}`);
|
|
89
|
+
console.log(" You can run `selftune ingest claude` manually to troubleshoot.");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check if any telemetry was produced after ingest
|
|
94
|
+
const telemetry = readJsonl<SessionTelemetryRecord>(TELEMETRY_LOG);
|
|
95
|
+
const skillRecords = readEffectiveSkillUsageRecords();
|
|
96
|
+
const queryRecords = readJsonl<QueryLogRecord>(QUERY_LOG);
|
|
97
|
+
const hasSessions = telemetry.length > 0 || queryRecords.length > 0;
|
|
98
|
+
const hasSkills = skillRecords.length > 0;
|
|
99
|
+
|
|
100
|
+
if (!hasSessions) {
|
|
101
|
+
console.log(" No sessions found. Checking for skills from hooks...");
|
|
102
|
+
if (hasSkills) {
|
|
103
|
+
const skillNames = [...new Set(skillRecords.map((r) => r.skill_name))].sort();
|
|
104
|
+
console.log(` Found ${skillNames.length} skill(s) from hooks: ${skillNames.join(", ")}`);
|
|
105
|
+
} else {
|
|
106
|
+
console.log(" No skills detected yet. Use your agent normally, then run");
|
|
107
|
+
console.log(" `selftune status` to see health scores.");
|
|
108
|
+
}
|
|
109
|
+
console.log("");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Step 3: Status
|
|
113
|
+
console.log("[3/3] Current status:");
|
|
114
|
+
console.log("");
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const auditEntries = readJsonl<EvolutionAuditEntry>(EVOLUTION_AUDIT_LOG);
|
|
118
|
+
const doctorResult = doctor();
|
|
119
|
+
|
|
120
|
+
const result = computeStatus(telemetry, skillRecords, queryRecords, auditEntries, doctorResult);
|
|
121
|
+
const output = formatStatus(result);
|
|
122
|
+
console.log(output);
|
|
123
|
+
|
|
124
|
+
// Step 4: Suggest top 3 skills to evolve
|
|
125
|
+
console.log("");
|
|
126
|
+
suggestSkillsToEvolve(result.skills);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
129
|
+
console.error(`Status failed: ${msg}`);
|
|
130
|
+
console.log("Run `selftune status` manually to troubleshoot.");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Suggest skills to evolve
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
function suggestSkillsToEvolve(skills: SkillStatus[]): void {
|
|
139
|
+
if (skills.length === 0) {
|
|
140
|
+
console.log("No skills found. Create skills and run sessions to get started.");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Score each skill: prioritize highest trigger count with lowest pass rate or no data
|
|
145
|
+
const scored: Array<{ name: string; score: number; reason: string }> = skills.map((s) => {
|
|
146
|
+
let score = 0;
|
|
147
|
+
let reason: string;
|
|
148
|
+
const passRateLabel = s.passRate !== null ? `${Math.round(s.passRate * 100)}%` : "unknown";
|
|
149
|
+
|
|
150
|
+
if (s.status === "UNGRADED" || s.status === "UNKNOWN") {
|
|
151
|
+
score = 100; // Highest priority: needs grading
|
|
152
|
+
reason = `needs grading — run \`selftune grade --skill ${s.name}\``;
|
|
153
|
+
} else if (s.status === "CRITICAL") {
|
|
154
|
+
score = 90;
|
|
155
|
+
reason = `pass rate ${passRateLabel} — needs evolution`;
|
|
156
|
+
} else if (s.status === "WARNING") {
|
|
157
|
+
score = 70;
|
|
158
|
+
reason = `pass rate ${passRateLabel} — could improve`;
|
|
159
|
+
} else {
|
|
160
|
+
score = 10;
|
|
161
|
+
reason = "healthy";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return { name: s.name, score, reason };
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Sort by score descending, take top 3
|
|
168
|
+
scored.sort((a, b) => b.score - a.score);
|
|
169
|
+
const top = scored.slice(0, 3).filter((s) => s.score > 10);
|
|
170
|
+
|
|
171
|
+
if (top.length === 0) {
|
|
172
|
+
console.log("All skills are healthy. No immediate actions needed.");
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log("Suggested next steps:");
|
|
177
|
+
for (const suggestion of top) {
|
|
178
|
+
console.log(` - ${suggestion.name}: ${suggestion.reason}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// CLI entry point
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
export async function cliMain(): Promise<void> {
|
|
187
|
+
// Check for --help
|
|
188
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
189
|
+
console.log(`selftune quickstart — Guided onboarding
|
|
190
|
+
|
|
191
|
+
Usage:
|
|
192
|
+
selftune quickstart
|
|
193
|
+
|
|
194
|
+
Steps:
|
|
195
|
+
1. Runs init if ~/.selftune/config.json doesn't exist
|
|
196
|
+
2. Runs ingest claude if session marker doesn't exist
|
|
197
|
+
3. Shows current status
|
|
198
|
+
4. Suggests top skills to evolve`);
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
await quickstart();
|
|
203
|
+
}
|