feat(sqlite): make worker deadlines adjustable with recovery guidance (#5818)

Expose a per-call SQLite worker deadline with exact CLI/MCP recovery controls,
parent-owned execution metadata and historical unknown preservation. Keep fixed
resource limits and cleanup admission intact. Share typed cleanup composition
with one captured-output owner and preserve the timeout after cleanup resolves.

Fixes #5812. Follow-up tracking: #5808. Existing CLI test-oracle failure: #5845.

Verified 155 SQLite tests (3 skipped), static/docs/discovery checks, six real
CLI/MCP pairs and 13 actual Codex sessions including four corrected deadline
recoveries. Three pre-dispatch discovery failures remain explicit, not passes.
Review findings include real retained-cleanup and fixture ownership regressions.

Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
This commit is contained in:
gensokyo-dev authored and GitHub committed 2026-10-21 16:45:46 +08:00
1 parent 5241597594
commit f801b2fbfd
15 files changed
+496 -49

No files matched your search

+17
View File
@@ -11,6 +11,10 @@ export const SQLITE_PROVIDER_IDENTITY = {
/** Default ordinary-table sample size when the caller selects a table. */
export const SQLITE_ROW_LIMIT_DEFAULT = 20;
/** Execution budget, bounded by the runtime's signed 32-bit timer range. */
export const DEFAULT_SQLITE_WORKER_TIMEOUT_MS = 30_000;
export const MAX_SQLITE_WORKER_TIMEOUT_MS = 2_147_483_647;
const workerTimeout = z.number().int().min(1).max(MAX_SQLITE_WORKER_TIMEOUT_MS);
const nonnegative = z.number().int().nonnegative();
const hex = z.string().regex(/^(?:[0-9a-f]{2})*$/);
@@ -27,6 +31,11 @@ export const inspectSqliteDatabaseInputSchema = z
path: localPathStringSchema.describe(
"Absolute path to an offline SQLite database snapshot",
),
worker_timeout_ms: workerTimeout
.optional()
.describe(
`Deadline in milliseconds for worker startup, queries and reply writing (default ${String(DEFAULT_SQLITE_WORKER_TIMEOUT_MS)}), not snapshot acquisition or the whole call. Allow client headroom for acquisition, reply reads, cleanup and delivery. Fixed byte/heap limits do not change.`,
),
table: z
.string()
.optional()
@@ -114,6 +123,11 @@ export const sqliteDatabaseSchema = z
name: z.literal("SQLite"),
version: z.string().min(1),
}),
worker_timeout_ms: workerTimeout
.exactOptional()
.describe(
"Actual parent-supervised worker deadline in milliseconds; absent in historical Evidence means unknown, not the default.",
),
database_encoding: encoding,
schema: z.strictObject({
scope: z.enum(["inventory", "selected_table", "database"]),
@@ -220,6 +234,9 @@ export const sqliteInspectionParameters = (
input: InspectSqliteDatabaseInput,
): Readonly<Record<string, JsonValue>> => ({
path: input.path,
...(input.worker_timeout_ms === undefined
? {}
: { worker_timeout_ms: input.worker_timeout_ms }),
...(input.table === undefined ? {} : { table: input.table }),
...(input.columns === undefined ? {} : { columns: input.columns }),
...(input.schema_scope === undefined