import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { ModelConfigurationService } from "../../apps/api/src/model-configuration.js"; import { RegistrationService } from "../../apps/api/src/registration.js"; import { MockResendAdapter } from "../../apps/api/src/resend-adapter.js"; const roots: string[] = []; const services: RegistrationService[] = []; const now = Date.parse("2026-08-02T15:00:00.000Z"); const ids = ["gemini-3.1-flash-image-preview", "gemini-3-pro-image-preview", "gpt-image-2"]; function evidence(file: string, value: unknown) { const root = process.env.DADA_EVIDENCE_DIR_RUNTIME; if (!root) return; const directory = resolve(root, "TDD-WP3-MDL-003-runtime-recommendation"); mkdirSync(dirname(resolve(directory, file)), { recursive: true }); writeFileSync(resolve(directory, file), `${JSON.stringify(value, null, 2)}\n`); } function harness() { const root = mkdtempSync(join(tmpdir(), "dada-wp3-02-runtime-unit-")); roots.push(root); const registration = new RegistrationService({ challengePepper: Buffer.alloc(32, 0x71), clock: () => now, currentPrivacyNoticeVersion: "p0a-registration-notice-v1", databasePath: join(root, "dada.sqlite3"), invitePepper: Buffer.alloc(32, 0x72), resend: new MockResendAdapter(), sessionPepper: Buffer.alloc(32, 0x73), }); services.push(registration); const models = new ModelConfigurationService({ database: registration.database, clock: () => now }); const candidates = structuredClone(models.read().models); for (const candidate of candidates) { candidate.contract_validation_status = "verified"; candidate.contract_evidence_ref = `fixture-${candidate.model_id}`; } models.replace({ actorId: "wp3-02-unit", expectedConfigSetVersion: 1, idempotencyKey: "wp3-02-unit-verified-00000000000000000001", models: candidates }); registration.database.prepare("UPDATE model_runtime_availability SET available_for_new_jobs = 1, reason = 'available', checked_at = ?").run(now); return { models, registration }; } afterEach(() => { for (const service of services.splice(0)) service.close(); for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true }); }); describe("TDD-WP3-MDL-003 runtime recommendation", () => { it("keeps configured default independent while deriving recommendation from runtime", () => { const { models, registration } = harness(); const before = registration.database.prepare("SELECT model_id, config_version, contract_fingerprint FROM model_config_versions ORDER BY model_id, config_version").all(); const states: unknown[] = []; const mark = (modelId: string, available: boolean, reason: string) => { registration.database.prepare("UPDATE model_runtime_availability SET available_for_new_jobs = ?, reason = ?, runtime_availability_version = runtime_availability_version + 1, checked_at = ? WHERE model_id = ?") .run(available ? 1 : 0, reason, now, modelId); const current = models.read(); states.push(current); return current; }; expect(models.read()).toMatchObject({ configured_default_model_id: ids[0], recommended_model_id: ids[0] }); expect(mark(ids[0], false, "gateway_balance_insufficient")).toMatchObject({ configured_default_model_id: ids[0], recommended_model_id: ids[1] }); mark(ids[1], false, "worker_degraded"); mark(ids[2], false, "gateway_paused"); expect(models.read().recommended_model_id).toBeNull(); expect(mark(ids[1], true, "available")).toMatchObject({ configured_default_model_id: ids[0], recommended_model_id: ids[1] }); expect(mark(ids[0], true, "available")).toMatchObject({ configured_default_model_id: ids[0], recommended_model_id: ids[0] }); expect(mark(ids[2], true, "available")).toMatchObject({ configured_default_model_id: ids[0], recommended_model_id: ids[0] }); const after = registration.database.prepare("SELECT model_id, config_version, contract_fingerprint FROM model_config_versions ORDER BY model_id, config_version").all(); expect(after).toEqual(before); expect(models.read().models.find((model) => model.model_id === ids[0])).toMatchObject({ enabled: true, is_default: true, recommendation_priority: 1 }); evidence("response.json", { states }); evidence("db-diff.json", { config_before: before, config_after: after, config_set_version: models.read().config_set_version }); evidence("screenshots/model-states.png", { generated_by: "tests/e2e/admin-models.spec.ts", state_count: states.length }); }); });