selftune 0.1.4 → 0.2.1
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 +156 -0
- package/.claude/agents/evolution-reviewer.md +180 -0
- package/.claude/agents/integration-guide.md +212 -0
- package/.claude/agents/pattern-analyst.md +160 -0
- package/CHANGELOG.md +46 -1
- package/README.md +105 -257
- 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/assets/BeforeAfter.gif +0 -0
- package/assets/FeedbackLoop.gif +0 -0
- package/assets/logo.svg +9 -0
- package/assets/skill-health-badge.svg +20 -0
- package/cli/selftune/activation-rules.ts +171 -0
- package/cli/selftune/badge/badge-data.ts +108 -0
- package/cli/selftune/badge/badge-svg.ts +212 -0
- package/cli/selftune/badge/badge.ts +99 -0
- package/cli/selftune/canonical-export.ts +183 -0
- package/cli/selftune/constants.ts +103 -1
- package/cli/selftune/contribute/bundle.ts +314 -0
- package/cli/selftune/contribute/contribute.ts +214 -0
- package/cli/selftune/contribute/sanitize.ts +162 -0
- package/cli/selftune/cron/setup.ts +266 -0
- package/cli/selftune/dashboard-contract.ts +202 -0
- package/cli/selftune/dashboard-server.ts +1049 -0
- package/cli/selftune/dashboard.ts +43 -156
- package/cli/selftune/eval/baseline.ts +248 -0
- package/cli/selftune/eval/composability-v2.ts +273 -0
- package/cli/selftune/eval/composability.ts +117 -0
- package/cli/selftune/eval/generate-unit-tests.ts +143 -0
- package/cli/selftune/eval/hooks-to-evals.ts +101 -16
- package/cli/selftune/eval/import-skillsbench.ts +221 -0
- package/cli/selftune/eval/synthetic-evals.ts +172 -0
- package/cli/selftune/eval/unit-test-cli.ts +152 -0
- package/cli/selftune/eval/unit-test.ts +196 -0
- package/cli/selftune/evolution/deploy-proposal.ts +142 -1
- package/cli/selftune/evolution/evidence.ts +26 -0
- package/cli/selftune/evolution/evolve-body.ts +586 -0
- package/cli/selftune/evolution/evolve.ts +825 -116
- package/cli/selftune/evolution/extract-patterns.ts +105 -16
- package/cli/selftune/evolution/pareto.ts +314 -0
- package/cli/selftune/evolution/propose-body.ts +171 -0
- package/cli/selftune/evolution/propose-description.ts +100 -2
- package/cli/selftune/evolution/propose-routing.ts +166 -0
- package/cli/selftune/evolution/refine-body.ts +141 -0
- package/cli/selftune/evolution/rollback.ts +21 -4
- package/cli/selftune/evolution/validate-body.ts +254 -0
- package/cli/selftune/evolution/validate-proposal.ts +257 -35
- package/cli/selftune/evolution/validate-routing.ts +177 -0
- package/cli/selftune/grading/auto-grade.ts +200 -0
- package/cli/selftune/grading/grade-session.ts +513 -42
- package/cli/selftune/grading/pre-gates.ts +104 -0
- package/cli/selftune/grading/results.ts +42 -0
- package/cli/selftune/hooks/auto-activate.ts +185 -0
- package/cli/selftune/hooks/evolution-guard.ts +165 -0
- package/cli/selftune/hooks/prompt-log.ts +172 -2
- package/cli/selftune/hooks/session-stop.ts +123 -3
- package/cli/selftune/hooks/skill-change-guard.ts +112 -0
- package/cli/selftune/hooks/skill-eval.ts +119 -3
- package/cli/selftune/index.ts +415 -48
- package/cli/selftune/ingestors/claude-replay.ts +377 -0
- 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 +573 -0
- package/cli/selftune/ingestors/opencode-ingest.ts +193 -17
- package/cli/selftune/init.ts +376 -16
- 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/memory/writer.ts +447 -0
- package/cli/selftune/monitoring/watch.ts +90 -16
- 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 +59 -33
- package/cli/selftune/sync.ts +627 -0
- package/cli/selftune/types.ts +525 -5
- package/cli/selftune/utils/canonical-log.ts +45 -0
- package/cli/selftune/utils/frontmatter.ts +217 -0
- package/cli/selftune/utils/hooks.ts +41 -0
- package/cli/selftune/utils/html.ts +27 -0
- package/cli/selftune/utils/llm-call.ts +103 -19
- 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 +307 -26
- package/cli/selftune/utils/trigger-check.ts +89 -0
- package/cli/selftune/utils/tui.ts +156 -0
- 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 +28 -11
- 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 +180 -33
- package/skill/Workflows/AutoActivation.md +145 -0
- package/skill/Workflows/Badge.md +124 -0
- package/skill/Workflows/Baseline.md +144 -0
- package/skill/Workflows/Composability.md +107 -0
- package/skill/Workflows/Contribute.md +94 -0
- package/skill/Workflows/Cron.md +132 -0
- package/skill/Workflows/Dashboard.md +214 -0
- package/skill/Workflows/Doctor.md +63 -14
- package/skill/Workflows/Evals.md +110 -18
- package/skill/Workflows/EvolutionMemory.md +154 -0
- package/skill/Workflows/Evolve.md +181 -21
- package/skill/Workflows/EvolveBody.md +159 -0
- package/skill/Workflows/Grade.md +36 -31
- package/skill/Workflows/ImportSkillsBench.md +117 -0
- package/skill/Workflows/Ingest.md +142 -21
- package/skill/Workflows/Initialize.md +91 -23
- package/skill/Workflows/Orchestrate.md +139 -0
- package/skill/Workflows/Replay.md +91 -0
- package/skill/Workflows/Rollback.md +23 -4
- package/skill/Workflows/Schedule.md +61 -0
- package/skill/Workflows/Sync.md +88 -0
- package/skill/Workflows/UnitTest.md +150 -0
- package/skill/Workflows/Watch.md +33 -1
- 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 +23 -0
- package/templates/activation-rules-default.json +27 -0
- package/templates/multi-skill-settings.json +64 -0
- package/templates/single-skill-settings.json +58 -0
- package/dashboard/index.html +0 -1119
package/cli/selftune/index.ts
CHANGED
|
@@ -3,48 +3,68 @@
|
|
|
3
3
|
* selftune CLI entry point.
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* selftune
|
|
7
|
-
* selftune
|
|
8
|
-
* selftune
|
|
9
|
-
* selftune
|
|
10
|
-
* selftune
|
|
11
|
-
* selftune
|
|
12
|
-
* selftune
|
|
13
|
-
* selftune
|
|
14
|
-
* selftune watch
|
|
15
|
-
* selftune doctor
|
|
16
|
-
* selftune
|
|
17
|
-
* selftune last
|
|
18
|
-
* selftune
|
|
6
|
+
* selftune ingest <agent> — Ingest agent sessions (claude, codex, opencode, openclaw, wrap-codex)
|
|
7
|
+
* selftune grade [mode] — Grade skill sessions (auto, baseline)
|
|
8
|
+
* selftune evolve [target] — Evolve skill descriptions (body, rollback)
|
|
9
|
+
* selftune eval <action> — Evaluation tools (generate, unit-test, import, composability)
|
|
10
|
+
* selftune sync — Sync source-truth telemetry across supported agents
|
|
11
|
+
* selftune orchestrate — Run autonomous core loop (sync → status → evolve → watch)
|
|
12
|
+
* selftune init — Initialize agent identity and config
|
|
13
|
+
* selftune status — Show skill health summary
|
|
14
|
+
* selftune watch — Monitor post-deploy skill health
|
|
15
|
+
* selftune doctor — Run health checks
|
|
16
|
+
* selftune dashboard — Open visual data dashboard
|
|
17
|
+
* selftune last — Show last session details
|
|
18
|
+
* selftune cron — Scheduling & automation (setup, list, remove)
|
|
19
|
+
* selftune badge — Generate skill health badges for READMEs
|
|
20
|
+
* selftune contribute — Export anonymized skill data for community
|
|
21
|
+
* selftune workflows — Discover and manage multi-skill workflows
|
|
22
|
+
* selftune quickstart — Guided onboarding: init, ingest, status, and suggestions
|
|
23
|
+
* selftune repair-skill-usage — Rebuild trustworthy skill usage from transcripts
|
|
24
|
+
* selftune export-canonical — Export canonical telemetry for downstream ingestion
|
|
25
|
+
* selftune hook <name> — Run a hook by name (prompt-log, session-stop, etc.)
|
|
19
26
|
*/
|
|
20
27
|
|
|
21
28
|
const command = process.argv[2];
|
|
22
29
|
|
|
23
|
-
if (
|
|
30
|
+
if (command === "--help" || command === "-h") {
|
|
24
31
|
console.log(`selftune — Skill observability and continuous improvement
|
|
25
32
|
|
|
26
33
|
Usage:
|
|
27
34
|
selftune <command> [options]
|
|
28
35
|
|
|
29
36
|
Commands:
|
|
37
|
+
ingest <agent> Ingest agent sessions (claude, codex, opencode, openclaw, wrap-codex)
|
|
38
|
+
grade [mode] Grade skill sessions (auto, baseline)
|
|
39
|
+
evolve [target] Evolve skill descriptions (body, rollback)
|
|
40
|
+
eval <action> Evaluation tools (generate, unit-test, import, composability)
|
|
41
|
+
sync Sync source-truth telemetry across supported agents
|
|
42
|
+
orchestrate Run autonomous core loop (sync → status → evolve → watch)
|
|
30
43
|
init Initialize agent identity and config
|
|
31
|
-
|
|
32
|
-
grade Grade a skill session
|
|
33
|
-
ingest-codex Ingest Codex rollout logs
|
|
34
|
-
ingest-opencode Ingest OpenCode sessions
|
|
35
|
-
wrap-codex Wrap codex exec with telemetry
|
|
36
|
-
evolve Evolve a skill description via failure patterns
|
|
37
|
-
rollback Rollback a skill to its pre-evolution state
|
|
44
|
+
status Show skill health summary
|
|
38
45
|
watch Monitor post-deploy skill health
|
|
39
46
|
doctor Run health checks
|
|
40
|
-
status Show skill health summary
|
|
41
|
-
last Show last session details
|
|
42
47
|
dashboard Open visual data dashboard
|
|
48
|
+
last Show last session details
|
|
49
|
+
cron Scheduling & automation (setup, list, remove)
|
|
50
|
+
badge Generate skill health badges for READMEs
|
|
51
|
+
contribute Export anonymized skill data for community
|
|
52
|
+
workflows Discover and manage multi-skill workflows
|
|
53
|
+
quickstart Guided onboarding: init, ingest, status, and suggestions
|
|
54
|
+
repair-skill-usage Rebuild trustworthy skill usage from transcripts
|
|
55
|
+
export-canonical Export canonical telemetry for downstream ingestion
|
|
56
|
+
hook <name> Run a hook by name (prompt-log, session-stop, etc.)
|
|
43
57
|
|
|
44
58
|
Run 'selftune <command> --help' for command-specific options.`);
|
|
45
59
|
process.exit(0);
|
|
46
60
|
}
|
|
47
61
|
|
|
62
|
+
if (!command) {
|
|
63
|
+
// Show status by default — same as `selftune status`
|
|
64
|
+
const { cliMain: statusMain } = await import("./status.js");
|
|
65
|
+
statusMain();
|
|
66
|
+
}
|
|
67
|
+
|
|
48
68
|
// Route to the appropriate subcommand module.
|
|
49
69
|
// We use dynamic imports so only the needed module is loaded.
|
|
50
70
|
// Each module exports a cliMain() function that the router calls explicitly,
|
|
@@ -52,43 +72,241 @@ Run 'selftune <command> --help' for command-specific options.`);
|
|
|
52
72
|
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
53
73
|
|
|
54
74
|
switch (command) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
// ── Grouped commands ──────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
case "ingest": {
|
|
78
|
+
const sub = process.argv[2];
|
|
79
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
80
|
+
console.log(`selftune ingest — Import agent sessions into shared telemetry logs
|
|
81
|
+
|
|
82
|
+
Usage:
|
|
83
|
+
selftune ingest <agent> [options]
|
|
84
|
+
|
|
85
|
+
Agents:
|
|
86
|
+
claude Replay Claude Code transcripts into logs
|
|
87
|
+
codex Ingest Codex rollout logs (experimental)
|
|
88
|
+
opencode Ingest OpenCode sessions (experimental)
|
|
89
|
+
openclaw Ingest OpenClaw sessions (experimental)
|
|
90
|
+
wrap-codex Wrap codex exec with real-time telemetry (experimental)
|
|
91
|
+
|
|
92
|
+
Run 'selftune ingest <agent> --help' for agent-specific options.`);
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
// Strip the subcommand so downstream sees the same argv as before
|
|
96
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
97
|
+
switch (sub) {
|
|
98
|
+
case "claude": {
|
|
99
|
+
const { cliMain } = await import("./ingestors/claude-replay.js");
|
|
100
|
+
cliMain();
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case "codex": {
|
|
104
|
+
const { cliMain } = await import("./ingestors/codex-rollout.js");
|
|
105
|
+
cliMain();
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case "opencode": {
|
|
109
|
+
const { cliMain } = await import("./ingestors/opencode-ingest.js");
|
|
110
|
+
cliMain();
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "openclaw": {
|
|
114
|
+
const { cliMain } = await import("./ingestors/openclaw-ingest.js");
|
|
115
|
+
cliMain();
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case "wrap-codex": {
|
|
119
|
+
const { cliMain } = await import("./ingestors/codex-wrapper.js");
|
|
120
|
+
await cliMain();
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
default:
|
|
124
|
+
console.error(
|
|
125
|
+
`Unknown ingest agent: ${sub}\nRun 'selftune ingest --help' for available agents.`,
|
|
126
|
+
);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
63
129
|
break;
|
|
64
130
|
}
|
|
131
|
+
|
|
65
132
|
case "grade": {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
133
|
+
const sub = process.argv[2];
|
|
134
|
+
if (sub === "--help" || sub === "-h") {
|
|
135
|
+
console.log(`selftune grade — Grade skill sessions
|
|
136
|
+
|
|
137
|
+
Usage:
|
|
138
|
+
selftune grade [options] Run the default session grader
|
|
139
|
+
selftune grade auto [options] Batch auto-grade sessions
|
|
140
|
+
selftune grade baseline [options] Measure baseline lift (no-skill comparison)
|
|
141
|
+
|
|
142
|
+
Run 'selftune grade <subcommand> --help' for subcommand-specific options.`);
|
|
143
|
+
process.exit(0);
|
|
144
|
+
}
|
|
145
|
+
// If no subcommand or starts with '-', run the default grader
|
|
146
|
+
if (!sub || sub.startsWith("-")) {
|
|
147
|
+
const { cliMain } = await import("./grading/grade-session.js");
|
|
148
|
+
await cliMain();
|
|
149
|
+
} else {
|
|
150
|
+
// Strip the subcommand
|
|
151
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
152
|
+
switch (sub) {
|
|
153
|
+
case "auto": {
|
|
154
|
+
const { cliMain } = await import("./grading/auto-grade.js");
|
|
155
|
+
await cliMain();
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case "baseline": {
|
|
159
|
+
const { cliMain } = await import("./eval/baseline.js");
|
|
160
|
+
await cliMain();
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
default:
|
|
164
|
+
console.error(
|
|
165
|
+
`Unknown grade mode: ${sub}\nRun 'selftune grade --help' for available modes.`,
|
|
166
|
+
);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
73
170
|
break;
|
|
74
171
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
172
|
+
|
|
173
|
+
case "evolve": {
|
|
174
|
+
const sub = process.argv[2];
|
|
175
|
+
if (sub === "--help" || sub === "-h") {
|
|
176
|
+
console.log(`selftune evolve — Evolve skill descriptions
|
|
177
|
+
|
|
178
|
+
Usage:
|
|
179
|
+
selftune evolve [options] Run description evolution
|
|
180
|
+
selftune evolve body [options] Evolve full body or routing table
|
|
181
|
+
selftune evolve rollback [options] Rollback a previous evolution
|
|
182
|
+
|
|
183
|
+
Run 'selftune evolve <subcommand> --help' for subcommand-specific options.`);
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}
|
|
186
|
+
// If no subcommand or starts with '-', run the default evolve
|
|
187
|
+
if (!sub || sub.startsWith("-")) {
|
|
188
|
+
const { cliMain } = await import("./evolution/evolve.js");
|
|
189
|
+
await cliMain();
|
|
190
|
+
} else {
|
|
191
|
+
// Strip the subcommand
|
|
192
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
193
|
+
switch (sub) {
|
|
194
|
+
case "body": {
|
|
195
|
+
const { cliMain } = await import("./evolution/evolve-body.js");
|
|
196
|
+
await cliMain();
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case "rollback": {
|
|
200
|
+
const { cliMain } = await import("./evolution/rollback.js");
|
|
201
|
+
await cliMain();
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
default:
|
|
205
|
+
console.error(
|
|
206
|
+
`Unknown evolve target: ${sub}\nRun 'selftune evolve --help' for available targets.`,
|
|
207
|
+
);
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
78
211
|
break;
|
|
79
212
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
213
|
+
|
|
214
|
+
case "eval": {
|
|
215
|
+
const sub = process.argv[2];
|
|
216
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
217
|
+
console.log(`selftune eval — Evaluation and testing tools
|
|
218
|
+
|
|
219
|
+
Usage:
|
|
220
|
+
selftune eval <action> [options]
|
|
221
|
+
|
|
222
|
+
Actions:
|
|
223
|
+
generate Generate eval sets from hook logs
|
|
224
|
+
unit-test Run or generate skill unit tests
|
|
225
|
+
import Import SkillsBench task corpus as eval entries
|
|
226
|
+
composability Analyze skill co-occurrence conflicts
|
|
227
|
+
|
|
228
|
+
Run 'selftune eval <action> --help' for action-specific options.`);
|
|
229
|
+
process.exit(0);
|
|
230
|
+
}
|
|
231
|
+
// Strip the subcommand
|
|
232
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
233
|
+
switch (sub) {
|
|
234
|
+
case "generate": {
|
|
235
|
+
const { cliMain } = await import("./eval/hooks-to-evals.js");
|
|
236
|
+
cliMain();
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case "unit-test": {
|
|
240
|
+
const { cliMain } = await import("./eval/unit-test-cli.js");
|
|
241
|
+
await cliMain();
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
case "import": {
|
|
245
|
+
const { cliMain } = await import("./eval/import-skillsbench.js");
|
|
246
|
+
cliMain();
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case "composability": {
|
|
250
|
+
if (process.argv[2] === "--help" || process.argv[2] === "-h") {
|
|
251
|
+
console.log(
|
|
252
|
+
"selftune eval composability --skill <name> [--window <days>] [--telemetry-log <path>]",
|
|
253
|
+
);
|
|
254
|
+
process.exit(0);
|
|
255
|
+
}
|
|
256
|
+
const { parseArgs } = await import("node:util");
|
|
257
|
+
const { readJsonl } = await import("./utils/jsonl.js");
|
|
258
|
+
const { TELEMETRY_LOG } = await import("./constants.js");
|
|
259
|
+
const { analyzeComposability } = await import("./eval/composability.js");
|
|
260
|
+
let values: ReturnType<typeof parseArgs>["values"];
|
|
261
|
+
try {
|
|
262
|
+
({ values } = parseArgs({
|
|
263
|
+
options: {
|
|
264
|
+
skill: { type: "string" },
|
|
265
|
+
window: { type: "string" },
|
|
266
|
+
"telemetry-log": { type: "string" },
|
|
267
|
+
},
|
|
268
|
+
strict: true,
|
|
269
|
+
}));
|
|
270
|
+
} catch (error) {
|
|
271
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
272
|
+
console.error(`Invalid arguments: ${message}`);
|
|
273
|
+
console.error("Run 'selftune eval composability --help' for usage.");
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
if (!values.skill) {
|
|
277
|
+
console.error("[ERROR] --skill <name> is required.");
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
const logPath = values["telemetry-log"] ?? TELEMETRY_LOG;
|
|
281
|
+
const telemetry = readJsonl(logPath);
|
|
282
|
+
const rawWindow = values.window as string | undefined;
|
|
283
|
+
if (rawWindow !== undefined && !/^[1-9]\d*$/.test(rawWindow)) {
|
|
284
|
+
console.error("Invalid --window value. Use a positive integer number of days.");
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
const windowSize = rawWindow === undefined ? undefined : Number(rawWindow);
|
|
288
|
+
const report = analyzeComposability(values.skill, telemetry, windowSize);
|
|
289
|
+
console.log(JSON.stringify(report, null, 2));
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
default:
|
|
293
|
+
console.error(
|
|
294
|
+
`Unknown eval action: ${sub}\nRun 'selftune eval --help' for available actions.`,
|
|
295
|
+
);
|
|
296
|
+
process.exit(1);
|
|
297
|
+
}
|
|
83
298
|
break;
|
|
84
299
|
}
|
|
85
|
-
|
|
86
|
-
|
|
300
|
+
|
|
301
|
+
// ── Unchanged commands ────────────────────────────────────────────────
|
|
302
|
+
|
|
303
|
+
case "init": {
|
|
304
|
+
const { cliMain } = await import("./init.js");
|
|
87
305
|
await cliMain();
|
|
88
306
|
break;
|
|
89
307
|
}
|
|
90
|
-
case "
|
|
91
|
-
const { cliMain } = await import("./
|
|
308
|
+
case "contribute": {
|
|
309
|
+
const { cliMain } = await import("./contribute/contribute.js");
|
|
92
310
|
await cliMain();
|
|
93
311
|
break;
|
|
94
312
|
}
|
|
@@ -116,9 +334,158 @@ switch (command) {
|
|
|
116
334
|
}
|
|
117
335
|
case "dashboard": {
|
|
118
336
|
const { cliMain } = await import("./dashboard.js");
|
|
337
|
+
await cliMain();
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case "cron":
|
|
341
|
+
case "schedule": {
|
|
342
|
+
const sub = process.argv[2];
|
|
343
|
+
if (sub === "--help" || sub === "-h" || (!sub && command === "cron")) {
|
|
344
|
+
console.log(`selftune cron — Scheduling & automation for selftune
|
|
345
|
+
|
|
346
|
+
Usage:
|
|
347
|
+
selftune cron <subcommand> [options]
|
|
348
|
+
|
|
349
|
+
Subcommands:
|
|
350
|
+
setup Auto-detect platform and install scheduled jobs (cron/launchd/systemd)
|
|
351
|
+
setup --platform openclaw Use OpenClaw-specific cron integration
|
|
352
|
+
list Show registered selftune cron jobs (OpenClaw)
|
|
353
|
+
remove Remove selftune cron jobs (OpenClaw)
|
|
354
|
+
|
|
355
|
+
Flags (setup):
|
|
356
|
+
--platform <name> Force a specific platform (openclaw, cron, launchd, systemd)
|
|
357
|
+
--dry-run Preview without installing
|
|
358
|
+
--tz <timezone> IANA timezone for job schedules (OpenClaw only)
|
|
359
|
+
--format, -f Alias for --platform (backward compat with schedule)
|
|
360
|
+
--install Write and activate artifacts (default for setup)
|
|
361
|
+
|
|
362
|
+
Aliases:
|
|
363
|
+
selftune schedule → selftune cron
|
|
364
|
+
|
|
365
|
+
Run 'selftune cron <subcommand> --help' for subcommand-specific options.`);
|
|
366
|
+
process.exit(0);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// If invoked as `selftune schedule` with no subcommand or with flags,
|
|
370
|
+
// route directly to the schedule module for backward compatibility
|
|
371
|
+
if (command === "schedule" && (!sub || sub.startsWith("-"))) {
|
|
372
|
+
const { cliMain } = await import("./schedule.js");
|
|
373
|
+
cliMain();
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Strip the subcommand so downstream sees clean argv
|
|
378
|
+
process.argv = [process.argv[0], process.argv[1], ...process.argv.slice(3)];
|
|
379
|
+
|
|
380
|
+
switch (sub) {
|
|
381
|
+
case "setup": {
|
|
382
|
+
// Check for --platform flag to decide which setup path
|
|
383
|
+
const platformIdx = process.argv.indexOf("--platform");
|
|
384
|
+
const platformVal = platformIdx >= 0 ? process.argv[platformIdx + 1] : undefined;
|
|
385
|
+
|
|
386
|
+
if (platformVal === "openclaw") {
|
|
387
|
+
// Remove --platform openclaw from argv before passing to cron/setup
|
|
388
|
+
process.argv = process.argv.filter((_, i) => i !== platformIdx && i !== platformIdx + 1);
|
|
389
|
+
const { cliMain } = await import("./cron/setup.js");
|
|
390
|
+
await cliMain();
|
|
391
|
+
} else if (platformVal) {
|
|
392
|
+
// Map --platform to --format for the schedule module
|
|
393
|
+
process.argv = process.argv.filter((_, i) => i !== platformIdx && i !== platformIdx + 1);
|
|
394
|
+
process.argv.push("--format", platformVal, "--install");
|
|
395
|
+
const { cliMain } = await import("./schedule.js");
|
|
396
|
+
cliMain();
|
|
397
|
+
} else {
|
|
398
|
+
// Auto-detect: install schedule artifacts for the current platform
|
|
399
|
+
process.argv.push("--install");
|
|
400
|
+
const { cliMain } = await import("./schedule.js");
|
|
401
|
+
cliMain();
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
case "list": {
|
|
406
|
+
const { cliMain } = await import("./cron/setup.js");
|
|
407
|
+
// Re-add 'list' so cron/setup.ts sees the subcommand
|
|
408
|
+
process.argv = [process.argv[0], process.argv[1], "list", ...process.argv.slice(2)];
|
|
409
|
+
await cliMain();
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case "remove": {
|
|
413
|
+
const { cliMain } = await import("./cron/setup.js");
|
|
414
|
+
// Re-add 'remove' so cron/setup.ts sees the subcommand
|
|
415
|
+
process.argv = [process.argv[0], process.argv[1], "remove", ...process.argv.slice(2)];
|
|
416
|
+
await cliMain();
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
default:
|
|
420
|
+
console.error(
|
|
421
|
+
`Unknown cron subcommand: ${sub}\nRun 'selftune cron --help' for available subcommands.`,
|
|
422
|
+
);
|
|
423
|
+
process.exit(1);
|
|
424
|
+
}
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
case "badge": {
|
|
428
|
+
const { cliMain } = await import("./badge/badge.js");
|
|
429
|
+
cliMain();
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
case "sync": {
|
|
433
|
+
const { cliMain } = await import("./sync.js");
|
|
119
434
|
cliMain();
|
|
120
435
|
break;
|
|
121
436
|
}
|
|
437
|
+
case "workflows": {
|
|
438
|
+
const { cliMain } = await import("./workflows/workflows.js");
|
|
439
|
+
await cliMain();
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
case "quickstart": {
|
|
443
|
+
const { cliMain } = await import("./quickstart.js");
|
|
444
|
+
await cliMain();
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
case "repair-skill-usage": {
|
|
448
|
+
const { cliMain } = await import("./repair/skill-usage.js");
|
|
449
|
+
cliMain();
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
case "export-canonical": {
|
|
453
|
+
const { cliMain } = await import("./canonical-export.js");
|
|
454
|
+
cliMain();
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
case "orchestrate": {
|
|
458
|
+
const { cliMain } = await import("./orchestrate.js");
|
|
459
|
+
await cliMain();
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
case "hook": {
|
|
463
|
+
// Dispatch to the appropriate hook file by name.
|
|
464
|
+
const hookName = process.argv[2]; // argv was shifted above
|
|
465
|
+
const HOOK_MAP: Record<string, string> = {
|
|
466
|
+
"prompt-log": "prompt-log.ts",
|
|
467
|
+
"session-stop": "session-stop.ts",
|
|
468
|
+
"skill-eval": "skill-eval.ts",
|
|
469
|
+
"auto-activate": "auto-activate.ts",
|
|
470
|
+
"skill-change-guard": "skill-change-guard.ts",
|
|
471
|
+
"evolution-guard": "evolution-guard.ts",
|
|
472
|
+
};
|
|
473
|
+
if (!hookName || !HOOK_MAP[hookName]) {
|
|
474
|
+
const available = Object.keys(HOOK_MAP).join(", ");
|
|
475
|
+
console.error(`Unknown hook: ${hookName ?? "(none)"}\nAvailable hooks: ${available}`);
|
|
476
|
+
process.exit(1);
|
|
477
|
+
}
|
|
478
|
+
const { resolve, dirname } = await import("node:path");
|
|
479
|
+
const { fileURLToPath } = await import("node:url");
|
|
480
|
+
const { spawnSync } = await import("node:child_process");
|
|
481
|
+
const hooksDir = resolve(dirname(fileURLToPath(import.meta.url)), "hooks");
|
|
482
|
+
const hookFile = resolve(hooksDir, HOOK_MAP[hookName]);
|
|
483
|
+
const result = spawnSync("bun", ["run", hookFile], {
|
|
484
|
+
stdio: "inherit",
|
|
485
|
+
});
|
|
486
|
+
process.exit(result.status ?? 1);
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
122
489
|
default:
|
|
123
490
|
console.error(`Unknown command: ${command}\nRun 'selftune --help' for available commands.`);
|
|
124
491
|
process.exit(1);
|