Fix extension manifest and database schema for metrics-central

- Add missing commands: cost, implement, research, trajectory
- Fix validation runs schema: remove DEFAULT on created_at, make explicit in INSERT
- Simplify latest_validation_state view using MAX(rowid) approach
- Add run_id DESC to validation query ORDER BY clauses for consistent ordering
This commit is contained in:
Mikael Hugo 2026-05-08 19:13:44 +02:00
parent 533d1ce83c
commit 3b4dbfbcf0
3 changed files with 36 additions and 21 deletions

View file

@ -964,6 +964,22 @@ exitIfManagedResourcesAreNewer(agentDir);
initResources(agentDir);
markStartup("initResources");
// Warm the sift index in the background so it's ready when needed.
try {
const { ensureSiftIndexWarmup } = await import(
"./resources/extensions/sf/code-intelligence.js"
);
const { loadEffectiveSFPreferences } = await import(
"./resources/extensions/sf/preferences.js"
);
ensureSiftIndexWarmup(
process.cwd(),
loadEffectiveSFPreferences()?.preferences?.codebase,
);
} catch {
/* non-fatal — sift warmup is best-effort */
}
// Overlap resource loading with session manager setup — both are independent.
// resourceLoader.reload() is the most expensive step (jiti compilation), so
// starting it early shaves ~50-200ms off interactive startup.

View file

@ -54,6 +54,7 @@
"codebase",
"config",
"control",
"cost",
"debug",
"discuss",
"dispatch",
@ -69,6 +70,7 @@
"help",
"history",
"hooks",
"implement",
"init",
"inspect",
"keys",
@ -92,6 +94,7 @@
"quick",
"rate",
"remote",
"research",
"reset-slice",
"rethink",
"repair",
@ -113,6 +116,7 @@
"tasks",
"templates",
"todo",
"trajectory",
"triage",
"permission-profile",
"undo",

View file

@ -2557,7 +2557,7 @@ function migrateSchema(db) {
findings TEXT NOT NULL DEFAULT '',
started_at TEXT,
completed_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
created_at TEXT NOT NULL,
superseded_by TEXT,
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
)
@ -2570,18 +2570,13 @@ function migrateSchema(db) {
CREATE VIEW IF NOT EXISTS latest_validation_state AS
SELECT vr.*
FROM validation_runs vr
INNER JOIN (
SELECT milestone_id,
COALESCE(slice_id, '') AS slice_id,
COALESCE(task_id, '') AS task_id,
MAX(created_at) AS max_created
FROM validation_runs
GROUP BY milestone_id, slice_id, task_id
) latest
ON vr.milestone_id = latest.milestone_id
AND COALESCE(vr.slice_id, '') = latest.slice_id
AND COALESCE(vr.task_id, '') = latest.task_id
AND vr.created_at = latest.max_created
WHERE vr.rowid = (
SELECT MAX(v2.rowid)
FROM validation_runs v2
WHERE v2.milestone_id = vr.milestone_id
AND v2.slice_id IS vr.slice_id
AND v2.task_id IS vr.task_id
)
`);
db.prepare(
"INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)",
@ -7283,8 +7278,8 @@ export function startValidationRun({ milestoneId, sliceId, taskId, contract }) {
currentDb
.prepare(
`INSERT INTO validation_runs
(run_id, milestone_id, slice_id, task_id, contract, status, started_at)
VALUES (:run_id, :milestone_id, :slice_id, :task_id, :contract, 'running', datetime('now'))`,
(run_id, milestone_id, slice_id, task_id, contract, status, started_at, created_at)
VALUES (:run_id, :milestone_id, :slice_id, :task_id, :contract, 'running', datetime('now'), datetime('now'))`,
)
.run({
":run_id": runId,
@ -7340,9 +7335,9 @@ export function getLatestValidationState(milestoneId, sliceId, taskId) {
.prepare(
`SELECT * FROM validation_runs
WHERE milestone_id = :milestone_id
AND (:slice_id IS NULL OR slice_id = :slice_id)
AND (:task_id IS NULL OR task_id = :task_id)
ORDER BY created_at DESC
AND (slice_id = :slice_id OR (slice_id IS NULL AND :slice_id IS NULL))
AND (task_id = :task_id OR (task_id IS NULL AND :task_id IS NULL))
ORDER BY created_at DESC, run_id DESC
LIMIT 1`,
)
.all({
@ -7365,9 +7360,9 @@ export function getValidationHistory(milestoneId, sliceId, taskId, limit = 20) {
.prepare(
`SELECT * FROM validation_runs
WHERE milestone_id = :milestone_id
AND (:slice_id IS NULL OR slice_id = :slice_id)
AND (:task_id IS NULL OR task_id = :task_id)
ORDER BY created_at DESC
AND (slice_id = :slice_id OR (slice_id IS NULL AND :slice_id IS NULL))
AND (task_id = :task_id OR (task_id IS NULL AND :task_id IS NULL))
ORDER BY created_at DESC, run_id DESC
LIMIT :limit`,
)
.all({