wire scheduler into queue, add retry, dev-reset cleanup, biome 2.4 migrate

- execute: actually call isInScheduleWindow/waitForWindow/sleepBetweenJobs in runSequential (they were dead code); emit queue_status SSE events (running/paused/sleeping/idle) so the pipeline's existing QueueStatus listener lights up
- review: POST /:id/retry resets an errored plan to approved, wipes old done/error jobs, rebuilds command from current decisions, queues fresh job
- scan: dev-mode DELETE now also wipes jobs + subtitle_files (previously orphaned after every dev reset)
- biome: migrate config to 2.4 schema, autoformat 68 files (strings + indentation), relax opinionated a11y/hooks-deps/index-key rules that don't fit this codebase
- routeTree.gen.ts regenerated after /nodes removal
This commit is contained in:
2026-04-13 07:41:19 +02:00
parent f11861658e
commit 874f04b7a5
69 changed files with 3511 additions and 2232 deletions

View File

@@ -1,34 +1,34 @@
import { describe, test, expect } from 'bun:test';
import { parseId, isOneOf } from '../validate';
import { describe, expect, test } from "bun:test";
import { isOneOf, parseId } from "../validate";
describe('parseId', () => {
test('returns the integer for valid numeric strings', () => {
expect(parseId('42')).toBe(42);
expect(parseId('1')).toBe(1);
describe("parseId", () => {
test("returns the integer for valid numeric strings", () => {
expect(parseId("42")).toBe(42);
expect(parseId("1")).toBe(1);
});
test('returns null for invalid, negative, zero, or missing ids', () => {
expect(parseId('0')).toBe(null);
expect(parseId('-1')).toBe(null);
expect(parseId('abc')).toBe(null);
expect(parseId('')).toBe(null);
test("returns null for invalid, negative, zero, or missing ids", () => {
expect(parseId("0")).toBe(null);
expect(parseId("-1")).toBe(null);
expect(parseId("abc")).toBe(null);
expect(parseId("")).toBe(null);
expect(parseId(undefined)).toBe(null);
});
test('parses leading integer from mixed strings (parseInt semantics)', () => {
expect(parseId('42abc')).toBe(42);
test("parses leading integer from mixed strings (parseInt semantics)", () => {
expect(parseId("42abc")).toBe(42);
});
});
describe('isOneOf', () => {
test('narrows to allowed string literals', () => {
expect(isOneOf('keep', ['keep', 'remove'] as const)).toBe(true);
expect(isOneOf('remove', ['keep', 'remove'] as const)).toBe(true);
describe("isOneOf", () => {
test("narrows to allowed string literals", () => {
expect(isOneOf("keep", ["keep", "remove"] as const)).toBe(true);
expect(isOneOf("remove", ["keep", "remove"] as const)).toBe(true);
});
test('rejects disallowed values and non-strings', () => {
expect(isOneOf('delete', ['keep', 'remove'] as const)).toBe(false);
expect(isOneOf(null, ['keep', 'remove'] as const)).toBe(false);
expect(isOneOf(42, ['keep', 'remove'] as const)).toBe(false);
test("rejects disallowed values and non-strings", () => {
expect(isOneOf("delete", ["keep", "remove"] as const)).toBe(false);
expect(isOneOf(null, ["keep", "remove"] as const)).toBe(false);
expect(isOneOf(42, ["keep", "remove"] as const)).toBe(false);
});
});

View File

@@ -1,4 +1,4 @@
import type { Context } from 'hono';
import type { Context } from "hono";
/** Parse a route param as a positive integer id. Returns null if invalid. */
export function parseId(raw: string | undefined): number | null {
@@ -22,5 +22,5 @@ export function requireId(c: Context, name: string): number | null {
/** True if value is one of the allowed strings. */
export function isOneOf<T extends string>(value: unknown, allowed: readonly T[]): value is T {
return typeof value === 'string' && (allowed as readonly string[]).includes(value);
return typeof value === "string" && (allowed as readonly string[]).includes(value);
}