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
|
@@ -239,6 +239,21 @@ CREATE TABLE IF NOT EXISTS upload_queue (
|
|
|
239
239
|
last_error TEXT
|
|
240
240
|
)`;
|
|
241
241
|
|
|
242
|
+
// -- Creator contribution staging --------------------------------------------
|
|
243
|
+
|
|
244
|
+
export const CREATE_CREATOR_CONTRIBUTION_STAGING = `
|
|
245
|
+
CREATE TABLE IF NOT EXISTS creator_contribution_staging (
|
|
246
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
247
|
+
dedupe_key TEXT NOT NULL,
|
|
248
|
+
skill_name TEXT NOT NULL,
|
|
249
|
+
creator_id TEXT NOT NULL,
|
|
250
|
+
payload_json TEXT NOT NULL,
|
|
251
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
252
|
+
staged_at TEXT NOT NULL,
|
|
253
|
+
updated_at TEXT NOT NULL,
|
|
254
|
+
last_error TEXT
|
|
255
|
+
)`;
|
|
256
|
+
|
|
242
257
|
// -- Canonical upload staging -------------------------------------------------
|
|
243
258
|
|
|
244
259
|
export const CREATE_CANONICAL_UPLOAD_STAGING = `
|
|
@@ -260,6 +275,20 @@ CREATE TABLE IF NOT EXISTS upload_watermarks (
|
|
|
260
275
|
updated_at TEXT NOT NULL
|
|
261
276
|
)`;
|
|
262
277
|
|
|
278
|
+
// -- Commit tracking table ----------------------------------------------------
|
|
279
|
+
|
|
280
|
+
export const CREATE_COMMIT_TRACKING = `
|
|
281
|
+
CREATE TABLE IF NOT EXISTS commit_tracking (
|
|
282
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
283
|
+
session_id TEXT NOT NULL,
|
|
284
|
+
commit_sha TEXT NOT NULL,
|
|
285
|
+
commit_title TEXT,
|
|
286
|
+
branch TEXT,
|
|
287
|
+
repo_remote TEXT,
|
|
288
|
+
timestamp TEXT NOT NULL,
|
|
289
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
290
|
+
)`;
|
|
291
|
+
|
|
263
292
|
// -- Metadata table -----------------------------------------------------------
|
|
264
293
|
|
|
265
294
|
export const CREATE_META = `
|
|
@@ -313,10 +342,19 @@ export const CREATE_INDEXES = [
|
|
|
313
342
|
// -- Alpha upload queue indexes ---------------------------------------------
|
|
314
343
|
`CREATE INDEX IF NOT EXISTS idx_upload_queue_status ON upload_queue(status)`,
|
|
315
344
|
`CREATE INDEX IF NOT EXISTS idx_upload_queue_type_status ON upload_queue(payload_type, status)`,
|
|
345
|
+
// -- Creator contribution staging indexes -----------------------------------
|
|
346
|
+
`CREATE INDEX IF NOT EXISTS idx_creator_contrib_status ON creator_contribution_staging(status)`,
|
|
347
|
+
`CREATE INDEX IF NOT EXISTS idx_creator_contrib_skill ON creator_contribution_staging(skill_name)`,
|
|
348
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_creator_contrib_dedup ON creator_contribution_staging(dedupe_key)`,
|
|
316
349
|
// -- Canonical upload staging indexes ---------------------------------------
|
|
317
350
|
`CREATE INDEX IF NOT EXISTS idx_staging_kind ON canonical_upload_staging(record_kind)`,
|
|
318
351
|
`CREATE INDEX IF NOT EXISTS idx_staging_session ON canonical_upload_staging(session_id)`,
|
|
319
352
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_staging_dedup ON canonical_upload_staging(record_kind, record_id)`,
|
|
353
|
+
// -- Commit tracking indexes ------------------------------------------------
|
|
354
|
+
`CREATE INDEX IF NOT EXISTS idx_commit_sha ON commit_tracking(commit_sha)`,
|
|
355
|
+
`CREATE INDEX IF NOT EXISTS idx_commit_session ON commit_tracking(session_id)`,
|
|
356
|
+
`CREATE INDEX IF NOT EXISTS idx_commit_ts ON commit_tracking(timestamp)`,
|
|
357
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_commit_dedup ON commit_tracking(session_id, commit_sha)`,
|
|
320
358
|
];
|
|
321
359
|
|
|
322
360
|
/**
|
|
@@ -353,6 +391,31 @@ export const MIGRATIONS = [
|
|
|
353
391
|
`ALTER TABLE execution_facts ADD COLUMN normalizer_version TEXT`,
|
|
354
392
|
`ALTER TABLE execution_facts ADD COLUMN capture_mode TEXT`,
|
|
355
393
|
`ALTER TABLE execution_facts ADD COLUMN raw_source_ref TEXT`,
|
|
394
|
+
// -- Win 2+3: File change metrics + token granularity + cost (execution_facts) --
|
|
395
|
+
`ALTER TABLE execution_facts ADD COLUMN files_changed INTEGER`,
|
|
396
|
+
`ALTER TABLE execution_facts ADD COLUMN lines_added INTEGER`,
|
|
397
|
+
`ALTER TABLE execution_facts ADD COLUMN lines_removed INTEGER`,
|
|
398
|
+
`ALTER TABLE execution_facts ADD COLUMN lines_modified INTEGER`,
|
|
399
|
+
`ALTER TABLE execution_facts ADD COLUMN cached_input_tokens INTEGER`,
|
|
400
|
+
`ALTER TABLE execution_facts ADD COLUMN reasoning_output_tokens INTEGER`,
|
|
401
|
+
`ALTER TABLE execution_facts ADD COLUMN cost_usd REAL`,
|
|
402
|
+
// -- Win 2+3: File change metrics + token granularity + cost (session_telemetry) --
|
|
403
|
+
`ALTER TABLE session_telemetry ADD COLUMN files_changed INTEGER`,
|
|
404
|
+
`ALTER TABLE session_telemetry ADD COLUMN lines_added INTEGER`,
|
|
405
|
+
`ALTER TABLE session_telemetry ADD COLUMN lines_removed INTEGER`,
|
|
406
|
+
`ALTER TABLE session_telemetry ADD COLUMN lines_modified INTEGER`,
|
|
407
|
+
`ALTER TABLE session_telemetry ADD COLUMN cached_input_tokens INTEGER`,
|
|
408
|
+
`ALTER TABLE session_telemetry ADD COLUMN reasoning_output_tokens INTEGER`,
|
|
409
|
+
`ALTER TABLE session_telemetry ADD COLUMN cost_usd REAL`,
|
|
410
|
+
// -- Generalized metrics: artifact count + session type --
|
|
411
|
+
`ALTER TABLE execution_facts ADD COLUMN artifact_count INTEGER`,
|
|
412
|
+
`ALTER TABLE execution_facts ADD COLUMN session_type TEXT`,
|
|
413
|
+
`ALTER TABLE session_telemetry ADD COLUMN artifact_count INTEGER`,
|
|
414
|
+
`ALTER TABLE session_telemetry ADD COLUMN session_type TEXT`,
|
|
415
|
+
// -- Session summary (heuristic, no LLM) --
|
|
416
|
+
`ALTER TABLE session_telemetry ADD COLUMN agent_summary TEXT`,
|
|
417
|
+
// -- SHA256 content hashing for upload dedup --
|
|
418
|
+
`ALTER TABLE canonical_upload_staging ADD COLUMN content_sha256 TEXT`,
|
|
356
419
|
];
|
|
357
420
|
|
|
358
421
|
/** Indexes that depend on migration columns — must run AFTER MIGRATIONS. */
|
|
@@ -360,6 +423,7 @@ export const POST_MIGRATION_INDEXES = [
|
|
|
360
423
|
`CREATE INDEX IF NOT EXISTS idx_skill_inv_query_triggered ON skill_invocations(query, triggered)`,
|
|
361
424
|
`CREATE INDEX IF NOT EXISTS idx_skill_inv_scope ON skill_invocations(skill_name, skill_scope, occurred_at)`,
|
|
362
425
|
`CREATE INDEX IF NOT EXISTS idx_skill_inv_dedup ON skill_invocations(session_id, skill_name, query, occurred_at, triggered)`,
|
|
426
|
+
`CREATE INDEX IF NOT EXISTS idx_staging_sha256 ON canonical_upload_staging(content_sha256)`,
|
|
363
427
|
];
|
|
364
428
|
|
|
365
429
|
/** All DDL statements in creation order. */
|
|
@@ -377,8 +441,10 @@ export const ALL_DDL = [
|
|
|
377
441
|
CREATE_GRADING_RESULTS,
|
|
378
442
|
CREATE_IMPROVEMENT_SIGNALS,
|
|
379
443
|
CREATE_UPLOAD_QUEUE,
|
|
444
|
+
CREATE_CREATOR_CONTRIBUTION_STAGING,
|
|
380
445
|
CREATE_UPLOAD_WATERMARKS,
|
|
381
446
|
CREATE_CANONICAL_UPLOAD_STAGING,
|
|
447
|
+
CREATE_COMMIT_TRACKING,
|
|
382
448
|
CREATE_META,
|
|
383
449
|
...CREATE_INDEXES,
|
|
384
450
|
];
|
|
@@ -16,9 +16,9 @@ import { parseArgs } from "node:util";
|
|
|
16
16
|
|
|
17
17
|
import { readAlphaIdentity } from "./alpha-identity.js";
|
|
18
18
|
import type { UploadCycleSummary } from "./alpha-upload/index.js";
|
|
19
|
-
import {
|
|
19
|
+
import { getOrchestrateLockPath, SELFTUNE_CONFIG_PATH } from "./constants.js";
|
|
20
20
|
import type { OrchestrateRunReport, OrchestrateRunSkillAction } from "./dashboard-contract.js";
|
|
21
|
-
import type { EvolveResult } from "./evolution/evolve.js";
|
|
21
|
+
import type { EvolveOptions, EvolveResult } from "./evolution/evolve.js";
|
|
22
22
|
import {
|
|
23
23
|
buildDefaultGradingOutputPath,
|
|
24
24
|
deriveExpectationsFromSkill,
|
|
@@ -74,7 +74,7 @@ interface LockInfo {
|
|
|
74
74
|
|
|
75
75
|
const LOCK_STALE_MS = 30 * 60 * 1000; // 30 minutes
|
|
76
76
|
|
|
77
|
-
export function acquireLock(lockPath: string =
|
|
77
|
+
export function acquireLock(lockPath: string = getOrchestrateLockPath()): boolean {
|
|
78
78
|
try {
|
|
79
79
|
if (existsSync(lockPath)) {
|
|
80
80
|
try {
|
|
@@ -98,7 +98,7 @@ export function acquireLock(lockPath: string = ORCHESTRATE_LOCK): boolean {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
export function releaseLock(lockPath: string =
|
|
101
|
+
export function releaseLock(lockPath: string = getOrchestrateLockPath()): void {
|
|
102
102
|
try {
|
|
103
103
|
unlinkSync(lockPath);
|
|
104
104
|
} catch {
|
|
@@ -377,6 +377,33 @@ export const MIN_CANDIDATE_EVIDENCE = 3;
|
|
|
377
377
|
/** Default cooldown hours after a deploy before re-evolving the same skill. */
|
|
378
378
|
export const DEFAULT_COOLDOWN_HOURS = 24;
|
|
379
379
|
|
|
380
|
+
type AutonomousEvolveDefaults = Pick<
|
|
381
|
+
EvolveOptions,
|
|
382
|
+
| "paretoEnabled"
|
|
383
|
+
| "candidateCount"
|
|
384
|
+
| "tokenEfficiencyEnabled"
|
|
385
|
+
| "withBaseline"
|
|
386
|
+
| "validationModel"
|
|
387
|
+
| "cheapLoop"
|
|
388
|
+
| "gateModel"
|
|
389
|
+
| "adaptiveGate"
|
|
390
|
+
| "proposalModel"
|
|
391
|
+
>;
|
|
392
|
+
|
|
393
|
+
// Keep the autonomous loop aligned with the evolve CLI defaults so scheduled
|
|
394
|
+
// runs stay cheap by default and still get a stronger gate before deploy.
|
|
395
|
+
const AUTONOMOUS_EVOLVE_DEFAULTS: AutonomousEvolveDefaults = {
|
|
396
|
+
paretoEnabled: true,
|
|
397
|
+
candidateCount: 3,
|
|
398
|
+
tokenEfficiencyEnabled: false,
|
|
399
|
+
withBaseline: false,
|
|
400
|
+
validationModel: "haiku",
|
|
401
|
+
cheapLoop: true,
|
|
402
|
+
gateModel: "sonnet",
|
|
403
|
+
adaptiveGate: true,
|
|
404
|
+
proposalModel: "haiku",
|
|
405
|
+
};
|
|
406
|
+
|
|
380
407
|
function candidatePriority(skill: SkillStatus, signalCount = 0): number {
|
|
381
408
|
const statusWeight = skill.status === "CRITICAL" ? 300 : skill.status === "WARNING" ? 200 : 100;
|
|
382
409
|
const missedWeight = Math.min(skill.missedQueries, 50);
|
|
@@ -1012,6 +1039,7 @@ export async function orchestrate(
|
|
|
1012
1039
|
maxIterations: 3,
|
|
1013
1040
|
gradingResults: _readGradingResults(candidate.skill),
|
|
1014
1041
|
syncFirst: false, // We already synced
|
|
1042
|
+
...AUTONOMOUS_EVOLVE_DEFAULTS,
|
|
1015
1043
|
});
|
|
1016
1044
|
|
|
1017
1045
|
candidate.evolveResult = evolveResult;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
CANONICAL_LOG,
|
|
7
|
+
EVOLUTION_AUDIT_LOG,
|
|
8
|
+
EVOLUTION_EVIDENCE_LOG,
|
|
9
|
+
ORCHESTRATE_RUN_LOG,
|
|
10
|
+
TELEMETRY_LOG,
|
|
11
|
+
} from "./constants.js";
|
|
12
|
+
import { getDb } from "./localdb/db.js";
|
|
13
|
+
import {
|
|
14
|
+
materializeFull,
|
|
15
|
+
materializeIncremental,
|
|
16
|
+
type MaterializeOptions,
|
|
17
|
+
type MaterializeResult,
|
|
18
|
+
} from "./localdb/materialize.js";
|
|
19
|
+
import { CLIError, handleCLIError } from "./utils/cli-error.js";
|
|
20
|
+
|
|
21
|
+
interface RecoverSummary {
|
|
22
|
+
mode: "incremental" | "full";
|
|
23
|
+
source: "legacy_jsonl_or_export_snapshot";
|
|
24
|
+
since: string | null;
|
|
25
|
+
force: boolean;
|
|
26
|
+
result: MaterializeResult;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function buildMaterializeOptions(values: Record<string, unknown>): MaterializeOptions {
|
|
30
|
+
return {
|
|
31
|
+
canonicalLogPath: (values["canonical-log"] as string | undefined) ?? CANONICAL_LOG,
|
|
32
|
+
telemetryLogPath: (values["telemetry-log"] as string | undefined) ?? TELEMETRY_LOG,
|
|
33
|
+
evolutionAuditPath:
|
|
34
|
+
(values["evolution-audit-log"] as string | undefined) ?? EVOLUTION_AUDIT_LOG,
|
|
35
|
+
evolutionEvidencePath:
|
|
36
|
+
(values["evolution-evidence-log"] as string | undefined) ?? EVOLUTION_EVIDENCE_LOG,
|
|
37
|
+
orchestrateRunLogPath:
|
|
38
|
+
(values["orchestrate-run-log"] as string | undefined) ?? ORCHESTRATE_RUN_LOG,
|
|
39
|
+
force: (values.force as boolean | undefined) ?? false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function printHumanSummary(summary: RecoverSummary): void {
|
|
44
|
+
const rows = [
|
|
45
|
+
`mode: ${summary.mode}`,
|
|
46
|
+
"source: legacy JSONL or explicit export snapshot",
|
|
47
|
+
`sessions: ${summary.result.sessions}`,
|
|
48
|
+
`prompts: ${summary.result.prompts}`,
|
|
49
|
+
`skill invocations: ${summary.result.skillInvocations}`,
|
|
50
|
+
`execution facts: ${summary.result.executionFacts}`,
|
|
51
|
+
`session telemetry: ${summary.result.sessionTelemetry}`,
|
|
52
|
+
`legacy skill usage: ${summary.result.skillUsage}`,
|
|
53
|
+
`evolution audit: ${summary.result.evolutionAudit}`,
|
|
54
|
+
`evolution evidence: ${summary.result.evolutionEvidence}`,
|
|
55
|
+
`orchestrate runs: ${summary.result.orchestrateRuns}`,
|
|
56
|
+
];
|
|
57
|
+
console.log(`selftune recover\n${rows.map((row) => ` ${row}`).join("\n")}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function cliMain(): void {
|
|
61
|
+
const { values } = parseArgs({
|
|
62
|
+
args: process.argv.slice(2),
|
|
63
|
+
options: {
|
|
64
|
+
full: { type: "boolean", default: false },
|
|
65
|
+
force: { type: "boolean", default: false },
|
|
66
|
+
since: { type: "string" },
|
|
67
|
+
json: { type: "boolean", default: false },
|
|
68
|
+
"canonical-log": { type: "string", default: CANONICAL_LOG },
|
|
69
|
+
"telemetry-log": { type: "string", default: TELEMETRY_LOG },
|
|
70
|
+
"evolution-audit-log": { type: "string", default: EVOLUTION_AUDIT_LOG },
|
|
71
|
+
"evolution-evidence-log": { type: "string", default: EVOLUTION_EVIDENCE_LOG },
|
|
72
|
+
"orchestrate-run-log": { type: "string", default: ORCHESTRATE_RUN_LOG },
|
|
73
|
+
help: { type: "boolean", short: "h", default: false },
|
|
74
|
+
},
|
|
75
|
+
strict: true,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if (values.help) {
|
|
79
|
+
console.log(`selftune recover — Recover SQLite from legacy/exported JSONL
|
|
80
|
+
|
|
81
|
+
Usage:
|
|
82
|
+
selftune recover [options]
|
|
83
|
+
|
|
84
|
+
Use this only for legacy backfill or explicit export-based recovery. Normal
|
|
85
|
+
operation should use \`selftune sync\`, which replays native source data into
|
|
86
|
+
SQLite and preserves alpha-upload compatibility.
|
|
87
|
+
|
|
88
|
+
Options:
|
|
89
|
+
--full Rebuild SQLite tables from scratch
|
|
90
|
+
--force Skip preflight rebuild guard for SQLite-only rows
|
|
91
|
+
--since <date> Incrementally materialize records on/after date
|
|
92
|
+
--canonical-log <path> Canonical JSONL path
|
|
93
|
+
--telemetry-log <path> Session telemetry JSONL path
|
|
94
|
+
--evolution-audit-log <path> Evolution audit JSONL path
|
|
95
|
+
--evolution-evidence-log <path> Evolution evidence JSONL path
|
|
96
|
+
--orchestrate-run-log <path> Orchestrate runs JSONL path
|
|
97
|
+
--json Output JSON summary
|
|
98
|
+
-h, --help Show this help`);
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (values.full && values.since) {
|
|
103
|
+
throw new CLIError(
|
|
104
|
+
"Cannot combine --full with --since.",
|
|
105
|
+
"INVALID_FLAG",
|
|
106
|
+
"Use either `selftune recover --full` or `selftune recover --since 2026-01-01`.",
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let sinceIso: string | null = null;
|
|
111
|
+
if (values.since) {
|
|
112
|
+
const parsed = new Date(values.since as string);
|
|
113
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
114
|
+
throw new CLIError(
|
|
115
|
+
`Invalid --since date: ${values.since}`,
|
|
116
|
+
"INVALID_FLAG",
|
|
117
|
+
"selftune recover --since 2026-01-01",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
sinceIso = parsed.toISOString();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const db = getDb();
|
|
124
|
+
const materializeOptions = buildMaterializeOptions(values);
|
|
125
|
+
if (!values.full) materializeOptions.since = sinceIso;
|
|
126
|
+
|
|
127
|
+
const result = values.full
|
|
128
|
+
? materializeFull(db, materializeOptions)
|
|
129
|
+
: materializeIncremental(db, materializeOptions);
|
|
130
|
+
|
|
131
|
+
const summary: RecoverSummary = {
|
|
132
|
+
mode: values.full ? "full" : "incremental",
|
|
133
|
+
source: "legacy_jsonl_or_export_snapshot",
|
|
134
|
+
since: sinceIso,
|
|
135
|
+
force: (values.force as boolean | undefined) ?? false,
|
|
136
|
+
result,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (values.json || !process.stdout.isTTY) {
|
|
140
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
printHumanSummary(summary);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (import.meta.main) {
|
|
148
|
+
try {
|
|
149
|
+
cliMain();
|
|
150
|
+
} catch (error) {
|
|
151
|
+
handleCLIError(error);
|
|
152
|
+
}
|
|
153
|
+
}
|