selftune 0.2.16 → 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.
- package/README.md +32 -22
- package/apps/local-dashboard/dist/assets/index-DnhnXQm6.js +60 -0
- package/apps/local-dashboard/dist/assets/index-_EcLywDg.css +1 -0
- package/apps/local-dashboard/dist/assets/vendor-table-BIiI3YhS.js +1 -0
- package/apps/local-dashboard/dist/assets/vendor-ui-CGEmUayx.js +12 -0
- package/apps/local-dashboard/dist/index.html +5 -5
- package/cli/selftune/alpha-upload/build-payloads.ts +14 -1
- package/cli/selftune/alpha-upload/client.ts +51 -1
- package/cli/selftune/alpha-upload/flush.ts +46 -5
- package/cli/selftune/alpha-upload/stage-canonical.ts +32 -10
- package/cli/selftune/alpha-upload-contract.ts +9 -0
- package/cli/selftune/constants.ts +92 -5
- package/cli/selftune/contribute/contribute.ts +30 -2
- package/cli/selftune/contribute/sanitize.ts +52 -5
- package/cli/selftune/contribution-config.ts +249 -0
- package/cli/selftune/contribution-relay.ts +177 -0
- package/cli/selftune/contribution-signals.ts +219 -0
- package/cli/selftune/contribution-staging.ts +147 -0
- package/cli/selftune/contributions.ts +532 -0
- package/cli/selftune/creator-contributions.ts +333 -0
- package/cli/selftune/dashboard-contract.ts +305 -1
- package/cli/selftune/dashboard-server.ts +47 -13
- package/cli/selftune/eval/family-overlap.ts +395 -0
- package/cli/selftune/eval/hooks-to-evals.ts +182 -28
- package/cli/selftune/eval/synthetic-evals.ts +298 -11
- package/cli/selftune/evolution/description-quality.ts +12 -11
- package/cli/selftune/evolution/evolve.ts +214 -51
- package/cli/selftune/evolution/validate-proposal.ts +9 -6
- package/cli/selftune/export.ts +2 -2
- package/cli/selftune/grading/grade-session.ts +20 -0
- package/cli/selftune/hooks/commit-track.ts +188 -0
- package/cli/selftune/hooks/prompt-log.ts +10 -1
- package/cli/selftune/hooks/session-stop.ts +2 -2
- package/cli/selftune/hooks/skill-eval.ts +15 -1
- package/cli/selftune/hooks/stdin-preview.ts +32 -0
- package/cli/selftune/index.ts +41 -5
- package/cli/selftune/ingestors/codex-rollout.ts +31 -35
- package/cli/selftune/ingestors/codex-wrapper.ts +32 -24
- package/cli/selftune/localdb/db.ts +2 -2
- package/cli/selftune/localdb/direct-write.ts +69 -6
- package/cli/selftune/localdb/queries.ts +1253 -37
- package/cli/selftune/localdb/schema.ts +66 -0
- package/cli/selftune/orchestrate.ts +32 -4
- package/cli/selftune/recover.ts +153 -0
- package/cli/selftune/repair/skill-usage.ts +363 -4
- package/cli/selftune/routes/actions.ts +35 -1
- package/cli/selftune/routes/analytics.ts +14 -0
- package/cli/selftune/routes/index.ts +1 -0
- package/cli/selftune/routes/overview.ts +150 -4
- package/cli/selftune/routes/skill-report.ts +648 -18
- package/cli/selftune/status.ts +81 -2
- package/cli/selftune/sync.ts +56 -2
- package/cli/selftune/trust-model.ts +66 -0
- package/cli/selftune/types.ts +80 -0
- package/cli/selftune/utils/skill-detection.ts +43 -0
- package/cli/selftune/utils/transcript.ts +210 -1
- package/cli/selftune/watchlist.ts +65 -0
- package/node_modules/@selftune/telemetry-contract/src/types.ts +11 -0
- package/package.json +1 -1
- package/packages/telemetry-contract/src/types.ts +11 -0
- package/packages/ui/src/components/ActivityTimeline.tsx +165 -150
- package/packages/ui/src/components/EvidenceViewer.tsx +335 -144
- package/packages/ui/src/components/EvolutionTimeline.tsx +58 -28
- package/packages/ui/src/components/OrchestrateRunsPanel.tsx +33 -16
- package/packages/ui/src/components/RecentActivityFeed.tsx +72 -41
- package/packages/ui/src/components/section-cards.tsx +12 -9
- package/packages/ui/src/primitives/card.tsx +1 -1
- package/skill/SKILL.md +40 -2
- package/skill/Workflows/AlphaUpload.md +4 -0
- package/skill/Workflows/Composability.md +64 -0
- package/skill/Workflows/Contribute.md +6 -3
- package/skill/Workflows/Contributions.md +97 -0
- package/skill/Workflows/CreatorContributions.md +74 -0
- package/skill/Workflows/Dashboard.md +31 -0
- package/skill/Workflows/Evals.md +57 -8
- package/skill/Workflows/Evolve.md +31 -13
- package/skill/Workflows/ExportCanonical.md +121 -0
- package/skill/Workflows/Hook.md +131 -0
- package/skill/Workflows/Ingest.md +7 -0
- package/skill/Workflows/Initialize.md +29 -9
- package/skill/Workflows/Orchestrate.md +27 -5
- package/skill/Workflows/Quickstart.md +94 -0
- package/skill/Workflows/Recover.md +84 -0
- package/skill/Workflows/RepairSkillUsage.md +95 -0
- package/skill/Workflows/Sync.md +18 -12
- package/skill/Workflows/Uninstall.md +82 -0
- package/skill/settings_snippet.json +11 -0
- package/apps/local-dashboard/dist/assets/index-BMIS6uUh.css +0 -2
- package/apps/local-dashboard/dist/assets/index-DOu3iLD9.js +0 -16
- package/apps/local-dashboard/dist/assets/vendor-table-pHbDxq36.js +0 -8
- package/apps/local-dashboard/dist/assets/vendor-ui-DIwlrGlb.js +0 -12
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
|
|
5
|
+
import { readAlphaIdentity } from "./alpha-identity.js";
|
|
6
|
+
import { SELFTUNE_CONFIG_PATH } from "./constants.js";
|
|
7
|
+
import {
|
|
8
|
+
type CreatorContributionConfig,
|
|
9
|
+
discoverCreatorContributionConfigs,
|
|
10
|
+
findCreatorContributionConfig,
|
|
11
|
+
getContributionConfigSearchRoots,
|
|
12
|
+
removeCreatorContributionConfig,
|
|
13
|
+
resolveContributionSkillPath,
|
|
14
|
+
writeCreatorContributionConfig,
|
|
15
|
+
} from "./contribution-config.js";
|
|
16
|
+
import { CLIError } from "./utils/cli-error.js";
|
|
17
|
+
import { handleCLIError } from "./utils/cli-error.js";
|
|
18
|
+
import { findInstalledSkillNames } from "./utils/skill-discovery.js";
|
|
19
|
+
|
|
20
|
+
function inferCreatorId(explicitCreatorId?: string): string | null {
|
|
21
|
+
if (explicitCreatorId?.trim()) return explicitCreatorId.trim();
|
|
22
|
+
const alpha = readAlphaIdentity(SELFTUNE_CONFIG_PATH);
|
|
23
|
+
return alpha?.cloud_user_id?.trim() || null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function printConfig(config: CreatorContributionConfig): void {
|
|
27
|
+
console.log(`${config.skill_name}`);
|
|
28
|
+
console.log(` creator_id: ${config.creator_id}`);
|
|
29
|
+
console.log(` skill_path: ${config.skill_path}`);
|
|
30
|
+
console.log(` signals: ${config.contribution.signals.join(", ")}`);
|
|
31
|
+
if (config.contribution.message) {
|
|
32
|
+
console.log(` message: ${config.contribution.message}`);
|
|
33
|
+
}
|
|
34
|
+
if (config.contribution.privacy_url) {
|
|
35
|
+
console.log(` privacy_url: ${config.contribution.privacy_url}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function printStatus(skillName?: string): void {
|
|
40
|
+
const searchRoots = getContributionConfigSearchRoots();
|
|
41
|
+
const installedSkills = [...findInstalledSkillNames(searchRoots)].sort();
|
|
42
|
+
const configuredSkillNames = new Set(
|
|
43
|
+
discoverCreatorContributionConfigs(searchRoots).map((c) => c.skill_name),
|
|
44
|
+
);
|
|
45
|
+
if (skillName) {
|
|
46
|
+
const config = findCreatorContributionConfig(skillName);
|
|
47
|
+
if (!config) {
|
|
48
|
+
console.log(`No creator contribution config found for "${skillName}".`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log("Creator contribution config:");
|
|
52
|
+
printConfig(config);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const configs = discoverCreatorContributionConfigs();
|
|
57
|
+
if (configs.length === 0) {
|
|
58
|
+
console.log("No creator contribution configs discovered.");
|
|
59
|
+
console.log("Use `selftune creator-contributions enable --skill <name>` to add one.");
|
|
60
|
+
} else {
|
|
61
|
+
console.log("Discovered creator contribution configs:");
|
|
62
|
+
for (const config of configs) {
|
|
63
|
+
printConfig(config);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const missingInstalled = installedSkills.filter((skill) => !configuredSkillNames.has(skill));
|
|
68
|
+
if (missingInstalled.length > 0) {
|
|
69
|
+
console.log("Installed skills without creator contribution config:");
|
|
70
|
+
for (const skill of missingInstalled) {
|
|
71
|
+
console.log(` ${skill}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface BulkEnableSkip {
|
|
77
|
+
skill_name: string;
|
|
78
|
+
reason: "already_configured" | "skill_path_not_found";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface BulkEnableResult {
|
|
82
|
+
written: string[];
|
|
83
|
+
skipped: BulkEnableSkip[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function enableCreatorContributionConfigs(options: {
|
|
87
|
+
skillName?: string;
|
|
88
|
+
all?: boolean;
|
|
89
|
+
prefix?: string;
|
|
90
|
+
explicitSkillPath?: string;
|
|
91
|
+
explicitCreatorId?: string;
|
|
92
|
+
signals: string[];
|
|
93
|
+
message?: string;
|
|
94
|
+
privacyUrl?: string;
|
|
95
|
+
}): BulkEnableResult {
|
|
96
|
+
const creatorId = inferCreatorId(options.explicitCreatorId);
|
|
97
|
+
if (!creatorId) {
|
|
98
|
+
throw new CLIError(
|
|
99
|
+
"Creator ID is required.",
|
|
100
|
+
"MISSING_FLAG",
|
|
101
|
+
"Pass --creator-id <id> or enroll alpha so cloud_user_id is available.",
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const searchRoots = getContributionConfigSearchRoots();
|
|
106
|
+
const targetSkills = options.all
|
|
107
|
+
? [...findInstalledSkillNames(searchRoots)]
|
|
108
|
+
.filter((name) => !options.prefix || name.startsWith(options.prefix))
|
|
109
|
+
.sort()
|
|
110
|
+
: options.skillName
|
|
111
|
+
? [options.skillName]
|
|
112
|
+
: [];
|
|
113
|
+
|
|
114
|
+
if (targetSkills.length === 0) {
|
|
115
|
+
throw new CLIError(
|
|
116
|
+
options.all
|
|
117
|
+
? `No installed skills found${options.prefix ? ` with prefix "${options.prefix}"` : ""}.`
|
|
118
|
+
: "Skill name is required.",
|
|
119
|
+
options.all ? "FILE_NOT_FOUND" : "MISSING_FLAG",
|
|
120
|
+
options.all
|
|
121
|
+
? "selftune creator-contributions status"
|
|
122
|
+
: "selftune creator-contributions enable --skill <name>",
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const result: BulkEnableResult = { written: [], skipped: [] };
|
|
127
|
+
for (const skillName of targetSkills) {
|
|
128
|
+
if (findCreatorContributionConfig(skillName, searchRoots)) {
|
|
129
|
+
result.skipped.push({ skill_name: skillName, reason: "already_configured" });
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const skillPath = resolveContributionSkillPath(
|
|
133
|
+
skillName,
|
|
134
|
+
options.all ? undefined : options.explicitSkillPath,
|
|
135
|
+
searchRoots,
|
|
136
|
+
);
|
|
137
|
+
if (!skillPath) {
|
|
138
|
+
result.skipped.push({ skill_name: skillName, reason: "skill_path_not_found" });
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
writeCreatorContributionConfig({
|
|
143
|
+
creator_id: creatorId,
|
|
144
|
+
skill_name: skillName,
|
|
145
|
+
skill_path: skillPath,
|
|
146
|
+
signals: options.signals,
|
|
147
|
+
message: options.message,
|
|
148
|
+
privacy_url: options.privacyUrl,
|
|
149
|
+
});
|
|
150
|
+
result.written.push(skillName);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function cliMain(): Promise<void> {
|
|
157
|
+
const sub = process.argv[2];
|
|
158
|
+
const rest = process.argv.slice(3);
|
|
159
|
+
|
|
160
|
+
if (sub === "--help" || sub === "-h") {
|
|
161
|
+
console.log(`selftune creator-contributions — Manage creator-side contribution configs
|
|
162
|
+
|
|
163
|
+
Usage:
|
|
164
|
+
selftune creator-contributions
|
|
165
|
+
selftune creator-contributions status [--skill <name>]
|
|
166
|
+
selftune creator-contributions enable --skill <name> [--skill-path <path>] [--creator-id <id>] [--signals a,b,c]
|
|
167
|
+
selftune creator-contributions enable --all [--prefix <prefix>] [--creator-id <id>] [--signals a,b,c]
|
|
168
|
+
selftune creator-contributions disable --skill <name> [--skill-path <path>]
|
|
169
|
+
|
|
170
|
+
Purpose:
|
|
171
|
+
Manage the local selftune.contribute.json file that a skill creator bundles
|
|
172
|
+
with a skill package. This is separate from:
|
|
173
|
+
selftune contributions End-user sharing preferences
|
|
174
|
+
selftune contribute Community export bundle`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const normalizedSub = sub ?? "status";
|
|
179
|
+
|
|
180
|
+
switch (normalizedSub) {
|
|
181
|
+
case "status": {
|
|
182
|
+
const { values } = parseArgs({
|
|
183
|
+
args: rest,
|
|
184
|
+
options: {
|
|
185
|
+
skill: { type: "string" },
|
|
186
|
+
help: { type: "boolean", short: "h", default: false },
|
|
187
|
+
},
|
|
188
|
+
strict: true,
|
|
189
|
+
});
|
|
190
|
+
if (values.help) {
|
|
191
|
+
console.log("Usage: selftune creator-contributions status [--skill <name>]");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
printStatus(values.skill);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
case "enable": {
|
|
198
|
+
const { values } = parseArgs({
|
|
199
|
+
args: rest,
|
|
200
|
+
options: {
|
|
201
|
+
skill: { type: "string" },
|
|
202
|
+
all: { type: "boolean", default: false },
|
|
203
|
+
prefix: { type: "string" },
|
|
204
|
+
"skill-path": { type: "string" },
|
|
205
|
+
"creator-id": { type: "string" },
|
|
206
|
+
signals: { type: "string", default: "trigger,grade,miss_category" },
|
|
207
|
+
message: { type: "string" },
|
|
208
|
+
"privacy-url": { type: "string" },
|
|
209
|
+
help: { type: "boolean", short: "h", default: false },
|
|
210
|
+
},
|
|
211
|
+
strict: true,
|
|
212
|
+
});
|
|
213
|
+
if (values.help) {
|
|
214
|
+
console.log(
|
|
215
|
+
"Usage: selftune creator-contributions enable (--skill <name> [--skill-path <path>] | --all [--prefix <prefix>]) [--creator-id <id>]",
|
|
216
|
+
);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (!values.all && !values.skill?.trim()) {
|
|
221
|
+
throw new CLIError(
|
|
222
|
+
"Pass either --skill <name> or --all.",
|
|
223
|
+
"MISSING_FLAG",
|
|
224
|
+
"selftune creator-contributions enable --skill <name>",
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const signals = (values.signals ?? "trigger,grade,miss_category")
|
|
229
|
+
.split(",")
|
|
230
|
+
.map((signal) => signal.trim())
|
|
231
|
+
.filter(Boolean);
|
|
232
|
+
const outcome = enableCreatorContributionConfigs({
|
|
233
|
+
skillName: values.skill?.trim(),
|
|
234
|
+
all: values.all,
|
|
235
|
+
prefix: values.prefix?.trim(),
|
|
236
|
+
explicitSkillPath: values["skill-path"],
|
|
237
|
+
explicitCreatorId: values["creator-id"],
|
|
238
|
+
signals,
|
|
239
|
+
message: values.message,
|
|
240
|
+
privacyUrl: values["privacy-url"],
|
|
241
|
+
});
|
|
242
|
+
if (values.all) {
|
|
243
|
+
console.log(
|
|
244
|
+
`Enabled creator contribution config for ${outcome.written.length} skills${values.prefix ? ` with prefix "${values.prefix}"` : ""}.`,
|
|
245
|
+
);
|
|
246
|
+
if (outcome.written.length > 0) {
|
|
247
|
+
for (const skill of outcome.written) {
|
|
248
|
+
const config = findCreatorContributionConfig(skill);
|
|
249
|
+
if (config) printConfig(config);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (outcome.skipped.length > 0) {
|
|
253
|
+
console.log(
|
|
254
|
+
`Skipped ${outcome.skipped.length} skills: ${outcome.skipped.map((entry) => entry.skill_name).join(", ")}`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const skillName = values.skill!.trim();
|
|
260
|
+
if (outcome.written.length === 0) {
|
|
261
|
+
const skip = outcome.skipped[0];
|
|
262
|
+
if (skip?.reason === "already_configured") {
|
|
263
|
+
throw new CLIError(
|
|
264
|
+
`A creator contribution config already exists for "${skillName}".`,
|
|
265
|
+
"FILE_EXISTS",
|
|
266
|
+
"Run `selftune creator-contributions status --skill <name>` to inspect it.",
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
throw new CLIError(
|
|
270
|
+
`Could not resolve SKILL.md for "${skillName}".`,
|
|
271
|
+
"FILE_NOT_FOUND",
|
|
272
|
+
"Pass --skill-path /path/to/SKILL.md",
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
const config = findCreatorContributionConfig(skillName);
|
|
276
|
+
console.log(`Enabled creator contribution config for "${skillName}".`);
|
|
277
|
+
if (config) printConfig(config);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
case "disable": {
|
|
281
|
+
const { values } = parseArgs({
|
|
282
|
+
args: rest,
|
|
283
|
+
options: {
|
|
284
|
+
skill: { type: "string" },
|
|
285
|
+
"skill-path": { type: "string" },
|
|
286
|
+
help: { type: "boolean", short: "h", default: false },
|
|
287
|
+
},
|
|
288
|
+
strict: true,
|
|
289
|
+
});
|
|
290
|
+
if (values.help) {
|
|
291
|
+
console.log(
|
|
292
|
+
"Usage: selftune creator-contributions disable --skill <name> [--skill-path <path>]",
|
|
293
|
+
);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const skillName = values.skill?.trim();
|
|
298
|
+
if (!skillName) {
|
|
299
|
+
throw new CLIError(
|
|
300
|
+
"Skill name is required.",
|
|
301
|
+
"MISSING_FLAG",
|
|
302
|
+
"selftune creator-contributions disable --skill <name>",
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
const skillPath = resolveContributionSkillPath(skillName, values["skill-path"]);
|
|
306
|
+
if (!skillPath) {
|
|
307
|
+
throw new CLIError(
|
|
308
|
+
`Could not resolve SKILL.md for "${skillName}".`,
|
|
309
|
+
"FILE_NOT_FOUND",
|
|
310
|
+
"Pass --skill-path /path/to/SKILL.md",
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const removed = removeCreatorContributionConfig(skillPath);
|
|
315
|
+
if (!removed) {
|
|
316
|
+
console.log(`No creator contribution config found for "${skillName}".`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
console.log(`Disabled creator contribution config for "${skillName}".`);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
default:
|
|
323
|
+
throw new CLIError(
|
|
324
|
+
`Unknown creator-contributions subcommand: ${normalizedSub}`,
|
|
325
|
+
"UNKNOWN_COMMAND",
|
|
326
|
+
"selftune creator-contributions --help",
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (import.meta.main) {
|
|
332
|
+
cliMain().catch(handleCLIError);
|
|
333
|
+
}
|
|
@@ -1,3 +1,71 @@
|
|
|
1
|
+
// -- Cursor-based pagination types -------------------------------------------
|
|
2
|
+
|
|
3
|
+
export interface PaginationCursor {
|
|
4
|
+
timestamp: string;
|
|
5
|
+
id: number | string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface PaginatedResult<T> {
|
|
9
|
+
items: T[];
|
|
10
|
+
next_cursor: PaginationCursor | null;
|
|
11
|
+
has_more: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Parse a JSON cursor param from a URL search string. Returns null on invalid input. */
|
|
15
|
+
export function parseCursorParam(value: string | null | undefined): PaginationCursor | null {
|
|
16
|
+
if (!value) return null;
|
|
17
|
+
try {
|
|
18
|
+
const parsed: unknown = JSON.parse(value);
|
|
19
|
+
if (parsed && typeof parsed === "object" && "timestamp" in parsed && "id" in parsed) {
|
|
20
|
+
const { timestamp, id } = parsed as { timestamp: unknown; id: unknown };
|
|
21
|
+
if (
|
|
22
|
+
typeof timestamp === "string" &&
|
|
23
|
+
(typeof id === "string" || (typeof id === "number" && Number.isFinite(id)))
|
|
24
|
+
) {
|
|
25
|
+
return { timestamp, id };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
// Invalid cursor JSON — treat as no cursor
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Parse an integer query param with bounds clamping. */
|
|
35
|
+
export function parseIntParam(value: string | null | undefined, defaultValue: number): number {
|
|
36
|
+
if (value == null) return defaultValue;
|
|
37
|
+
const n = Number.parseInt(value, 10);
|
|
38
|
+
return Number.isNaN(n) ? defaultValue : Math.max(1, Math.min(n, 10000));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// -- Paginated overview payload (returned when cursor params are provided) ----
|
|
42
|
+
|
|
43
|
+
export interface OverviewPaginatedPayload {
|
|
44
|
+
telemetry_page: PaginatedResult<TelemetryRecord>;
|
|
45
|
+
skills_page: PaginatedResult<SkillUsageRecord>;
|
|
46
|
+
evolution: EvolutionEntry[];
|
|
47
|
+
counts: OverviewPayload["counts"];
|
|
48
|
+
unmatched_queries: UnmatchedQuery[];
|
|
49
|
+
pending_proposals: PendingProposal[];
|
|
50
|
+
active_sessions: number;
|
|
51
|
+
recent_activity: RecentActivityItem[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface SkillReportPaginatedPayload extends Omit<
|
|
55
|
+
SkillReportPayload,
|
|
56
|
+
"recent_invocations"
|
|
57
|
+
> {
|
|
58
|
+
invocations_page: PaginatedResult<{
|
|
59
|
+
timestamp: string;
|
|
60
|
+
session_id: string;
|
|
61
|
+
query: string;
|
|
62
|
+
triggered: boolean;
|
|
63
|
+
source: string | null;
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// -- Core record types -------------------------------------------------------
|
|
68
|
+
|
|
1
69
|
export interface TelemetryRecord {
|
|
2
70
|
timestamp: string;
|
|
3
71
|
session_id: string;
|
|
@@ -66,6 +134,65 @@ export interface SkillSummary {
|
|
|
66
134
|
unique_sessions: number;
|
|
67
135
|
last_seen: string | null;
|
|
68
136
|
has_evidence: boolean;
|
|
137
|
+
routing_confidence: number | null;
|
|
138
|
+
confidence_coverage: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// -- Autonomy-first overview types -------------------------------------------
|
|
142
|
+
|
|
143
|
+
export type AutonomyStatusLevel = "healthy" | "watching" | "needs_review" | "blocked";
|
|
144
|
+
|
|
145
|
+
export interface AutonomyStatus {
|
|
146
|
+
level: AutonomyStatusLevel;
|
|
147
|
+
summary: string;
|
|
148
|
+
last_run: string | null;
|
|
149
|
+
skills_observed: number;
|
|
150
|
+
pending_reviews: number;
|
|
151
|
+
attention_required: number;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export type AttentionCategory =
|
|
155
|
+
| "needs_review"
|
|
156
|
+
| "regression"
|
|
157
|
+
| "low_trust"
|
|
158
|
+
| "polluted"
|
|
159
|
+
| "blocked";
|
|
160
|
+
|
|
161
|
+
export interface AttentionItem {
|
|
162
|
+
skill_name: string;
|
|
163
|
+
category: AttentionCategory;
|
|
164
|
+
severity: "critical" | "warning" | "info";
|
|
165
|
+
reason: string;
|
|
166
|
+
recommended_action: string;
|
|
167
|
+
timestamp: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export type TrustBucket = "at_risk" | "improving" | "uncertain" | "stable";
|
|
171
|
+
|
|
172
|
+
export interface TrustWatchlistEntry {
|
|
173
|
+
skill_name: string;
|
|
174
|
+
bucket: TrustBucket;
|
|
175
|
+
trust_state: TrustState;
|
|
176
|
+
reason: string;
|
|
177
|
+
pass_rate: number | null;
|
|
178
|
+
checks: number;
|
|
179
|
+
last_seen: string | null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export type DecisionKind =
|
|
183
|
+
| "proposal_created"
|
|
184
|
+
| "proposal_rejected"
|
|
185
|
+
| "validation_failed"
|
|
186
|
+
| "proposal_deployed"
|
|
187
|
+
| "rollback_triggered"
|
|
188
|
+
| "regression_found";
|
|
189
|
+
|
|
190
|
+
export interface AutonomousDecision {
|
|
191
|
+
timestamp: string;
|
|
192
|
+
kind: DecisionKind;
|
|
193
|
+
skill_name: string;
|
|
194
|
+
proposal_id?: string;
|
|
195
|
+
summary: string;
|
|
69
196
|
}
|
|
70
197
|
|
|
71
198
|
export interface OverviewPayload {
|
|
@@ -90,6 +217,11 @@ export interface OverviewResponse {
|
|
|
90
217
|
overview: OverviewPayload;
|
|
91
218
|
skills: SkillSummary[];
|
|
92
219
|
version?: string;
|
|
220
|
+
watched_skills: string[];
|
|
221
|
+
autonomy_status: AutonomyStatus;
|
|
222
|
+
attention_queue: AttentionItem[];
|
|
223
|
+
trust_watchlist: TrustWatchlistEntry[];
|
|
224
|
+
recent_decisions: AutonomousDecision[];
|
|
93
225
|
}
|
|
94
226
|
|
|
95
227
|
export interface EvidenceEntry {
|
|
@@ -120,6 +252,8 @@ export interface CanonicalInvocation {
|
|
|
120
252
|
source?: string | null;
|
|
121
253
|
skill_path?: string | null;
|
|
122
254
|
skill_scope?: string | null;
|
|
255
|
+
observation_kind?: ObservationKind;
|
|
256
|
+
historical_context?: HistoricalContext | null;
|
|
123
257
|
}
|
|
124
258
|
|
|
125
259
|
export interface PromptSample {
|
|
@@ -198,6 +332,48 @@ export interface OrchestrateRunsResponse {
|
|
|
198
332
|
runs: OrchestrateRunReport[];
|
|
199
333
|
}
|
|
200
334
|
|
|
335
|
+
// -- Performance analytics response -------------------------------------------
|
|
336
|
+
|
|
337
|
+
export interface AnalyticsResponse {
|
|
338
|
+
/** Daily pass rate trend (last 90 days, bucketed by day) */
|
|
339
|
+
pass_rate_trend: Array<{
|
|
340
|
+
date: string;
|
|
341
|
+
pass_rate: number;
|
|
342
|
+
total_checks: number;
|
|
343
|
+
}>;
|
|
344
|
+
|
|
345
|
+
/** Skills ranked by pass rate with trend direction */
|
|
346
|
+
skill_rankings: Array<{
|
|
347
|
+
skill_name: string;
|
|
348
|
+
pass_rate: number;
|
|
349
|
+
total_checks: number;
|
|
350
|
+
triggered_count: number;
|
|
351
|
+
}>;
|
|
352
|
+
|
|
353
|
+
/** Daily check counts for heatmap (last 84 days / 12 weeks) */
|
|
354
|
+
daily_activity: Array<{
|
|
355
|
+
date: string;
|
|
356
|
+
checks: number;
|
|
357
|
+
}>;
|
|
358
|
+
|
|
359
|
+
/** Evolution impact — before/after pass rates for deployed evolutions */
|
|
360
|
+
evolution_impact: Array<{
|
|
361
|
+
skill_name: string;
|
|
362
|
+
proposal_id: string;
|
|
363
|
+
deployed_at: string;
|
|
364
|
+
pass_rate_before: number;
|
|
365
|
+
pass_rate_after: number;
|
|
366
|
+
}>;
|
|
367
|
+
|
|
368
|
+
/** Aggregate summary */
|
|
369
|
+
summary: {
|
|
370
|
+
total_evolutions: number;
|
|
371
|
+
avg_improvement: number;
|
|
372
|
+
total_checks_30d: number;
|
|
373
|
+
active_skills: number;
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
|
|
201
377
|
// -- Health endpoint response -------------------------------------------------
|
|
202
378
|
|
|
203
379
|
export interface HealthResponse {
|
|
@@ -220,7 +396,133 @@ export interface HealthResponse {
|
|
|
220
396
|
// -- Doctor / health check types ----------------------------------------------
|
|
221
397
|
export type { DoctorResult, HealthCheck, HealthStatus } from "./types.js";
|
|
222
398
|
|
|
223
|
-
|
|
399
|
+
// -- Execution metrics (aggregated from execution_facts enrichment columns) ---
|
|
400
|
+
|
|
401
|
+
export interface ExecutionMetrics {
|
|
402
|
+
avg_files_changed: number;
|
|
403
|
+
total_lines_added: number;
|
|
404
|
+
total_lines_removed: number;
|
|
405
|
+
total_cost_usd: number;
|
|
406
|
+
avg_cost_usd: number;
|
|
407
|
+
cached_input_tokens_total: number;
|
|
408
|
+
reasoning_output_tokens_total: number;
|
|
409
|
+
artifact_count: number;
|
|
410
|
+
session_type_distribution: Record<string, number>;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// -- Commit summary (aggregated from commit_tracking table) -------------------
|
|
414
|
+
|
|
415
|
+
export interface CommitRecord {
|
|
416
|
+
commit_sha: string;
|
|
417
|
+
commit_title: string | null;
|
|
418
|
+
branch: string | null;
|
|
419
|
+
repo_remote: string | null;
|
|
420
|
+
timestamp: string;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export interface CommitSummary {
|
|
424
|
+
total_commits: number;
|
|
425
|
+
unique_branches: number;
|
|
426
|
+
recent_commits: Array<{ sha: string; title: string; branch: string; timestamp: string }>;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// -- Trust-oriented types for skill report ------------------------------------
|
|
430
|
+
|
|
431
|
+
export type TrustState =
|
|
432
|
+
| "low_sample"
|
|
433
|
+
| "observed"
|
|
434
|
+
| "watch"
|
|
435
|
+
| "validated"
|
|
436
|
+
| "deployed"
|
|
437
|
+
| "rolled_back";
|
|
438
|
+
|
|
439
|
+
export type ObservationKind =
|
|
440
|
+
| "canonical"
|
|
441
|
+
| "repaired_trigger"
|
|
442
|
+
| "repaired_contextual_miss"
|
|
443
|
+
| "legacy_materialized";
|
|
444
|
+
|
|
445
|
+
export type HistoricalContext = "previously_missed";
|
|
446
|
+
|
|
447
|
+
export interface ExampleRow {
|
|
448
|
+
timestamp: string | null;
|
|
449
|
+
session_id: string;
|
|
450
|
+
query_text: string;
|
|
451
|
+
triggered: boolean;
|
|
452
|
+
confidence: number | null;
|
|
453
|
+
invocation_mode: string | null;
|
|
454
|
+
prompt_kind: string | null;
|
|
455
|
+
source: string | null;
|
|
456
|
+
platform: string | null;
|
|
457
|
+
workspace_path: string | null;
|
|
458
|
+
query_origin: "inline_query" | "matched_prompt" | "missing";
|
|
459
|
+
is_system_like: boolean;
|
|
460
|
+
observation_kind: ObservationKind;
|
|
461
|
+
historical_context?: HistoricalContext | null;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export interface TrustFields {
|
|
465
|
+
trust: {
|
|
466
|
+
state: TrustState;
|
|
467
|
+
summary: string;
|
|
468
|
+
};
|
|
469
|
+
coverage: {
|
|
470
|
+
checks: number;
|
|
471
|
+
sessions: number;
|
|
472
|
+
workspaces: number;
|
|
473
|
+
first_seen: string | null;
|
|
474
|
+
last_seen: string | null;
|
|
475
|
+
};
|
|
476
|
+
evidence_quality: {
|
|
477
|
+
prompt_link_rate: number;
|
|
478
|
+
inline_query_rate: number;
|
|
479
|
+
user_prompt_rate: number;
|
|
480
|
+
meta_prompt_rate: number;
|
|
481
|
+
internal_prompt_rate: number;
|
|
482
|
+
no_prompt_rate: number;
|
|
483
|
+
system_like_rate: number;
|
|
484
|
+
invocation_mode_coverage: number;
|
|
485
|
+
confidence_coverage: number;
|
|
486
|
+
source_coverage: number;
|
|
487
|
+
scope_coverage: number;
|
|
488
|
+
};
|
|
489
|
+
routing_quality: {
|
|
490
|
+
missed_triggers: number;
|
|
491
|
+
miss_rate: number;
|
|
492
|
+
avg_confidence: number | null;
|
|
493
|
+
confidence_coverage: number;
|
|
494
|
+
low_confidence_rate: number | null;
|
|
495
|
+
};
|
|
496
|
+
evolution_state: {
|
|
497
|
+
has_evidence: boolean;
|
|
498
|
+
has_pending_proposals: boolean;
|
|
499
|
+
latest_action: string | null;
|
|
500
|
+
latest_timestamp: string | null;
|
|
501
|
+
evidence_rows: number;
|
|
502
|
+
evolution_rows: number;
|
|
503
|
+
};
|
|
504
|
+
data_hygiene: {
|
|
505
|
+
naming_variants: string[];
|
|
506
|
+
source_breakdown: Array<{ source: string; count: number }>;
|
|
507
|
+
prompt_kind_breakdown: Array<{ kind: string; count: number }>;
|
|
508
|
+
observation_breakdown: Array<{ kind: ObservationKind; count: number }>;
|
|
509
|
+
raw_checks: number;
|
|
510
|
+
operational_checks: number;
|
|
511
|
+
internal_prompt_rows: number;
|
|
512
|
+
internal_prompt_rate: number;
|
|
513
|
+
legacy_rows: number;
|
|
514
|
+
legacy_rate: number;
|
|
515
|
+
repaired_rows: number;
|
|
516
|
+
repaired_rate: number;
|
|
517
|
+
};
|
|
518
|
+
examples: {
|
|
519
|
+
good: ExampleRow[];
|
|
520
|
+
missed: ExampleRow[];
|
|
521
|
+
noisy: ExampleRow[];
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export interface SkillReportResponse extends SkillReportPayload, TrustFields {
|
|
224
526
|
evolution: EvolutionEntry[];
|
|
225
527
|
pending_proposals: PendingProposal[];
|
|
226
528
|
token_usage: {
|
|
@@ -242,6 +544,8 @@ export interface SkillReportResponse extends SkillReportPayload {
|
|
|
242
544
|
};
|
|
243
545
|
prompt_samples: PromptSample[];
|
|
244
546
|
session_metadata: SessionMeta[];
|
|
547
|
+
execution_metrics?: ExecutionMetrics | null;
|
|
548
|
+
commit_summary?: CommitSummary | null;
|
|
245
549
|
description_quality?: {
|
|
246
550
|
composite: number;
|
|
247
551
|
criteria: {
|