```ts
export function preemptFirstOverrun(jobs: Array<Record<string, unknown>>): string {
  const seen = new Set<string>();
  for (const job of jobs) {
    if (typeof job.name !== "string" || job.name === "") {
      throw new Error("name must be a non-empty string");
    }
    if (seen.has(job.name)) {
      throw new Error(`name repeated: ${job.name}`);
    }
    seen.add(job.name);
    if (!Number.isInteger(job.at) || (job.at as number) < 0) {
      throw new Error("at must be a non-negative integer");
    }
    if (!Number.isInteger(job.work) || (job.work as number) <= 0) {
      throw new Error("work must be a positive integer");
    }
    if (!Number.isInteger(job.due) || (job.due as number) <= 0) {
      throw new Error("due must be a positive integer");
    }
  }

  const remaining = new Map<string, number>();
  const at = new Map<string, number>();
  const due = new Map<string, number>();
  for (const job of jobs) {
    remaining.set(job.name as string, job.work as number);
    at.set(job.name as string, job.at as number);
    due.set(job.name as string, job.due as number);
  }

  const finish = new Map<string, number>();
  let clock = 0;
  let currentJob: string | null = null;

  while (finish.size < jobs.length) {
    const ready = [...remaining.keys()].filter(
      (name) => !finish.has(name) && at.get(name)! <= clock,
    );

    if (ready.length === 0) {
      if (currentJob !== null && remaining.get(currentJob)! > 0) {
        clock += remaining.get(currentJob)!;
        remaining.set(currentJob, 0);
        finish.set(currentJob, clock);
      } else {
        clock = Math.min(
          ...[...remaining.keys()]
            .filter((name) => !finish.has(name))
            .map((name) => at.get(name)!),
        );
      }
      continue;
    }

    ready.sort((a, b) => due.get(a)! - due.get(b)! || (a < b ? -1 : 1));

    if (currentJob !== null && remaining.get(currentJob)! > 0) {
      const currentDue = due.get(currentJob)!;
      const nextDue = due.get(ready[0])!;
      if (nextDue < currentDue) {
        clock += remaining.get(currentJob)!;
        remaining.set(currentJob, 0);
        finish.set(currentJob, clock);
      }
    }

    if (currentJob === null || ready[0] !== currentJob) {
      currentJob = ready[0];
    }

    const workToFinish = Math.min(remaining.get(currentJob)!, due.get(currentJob)! - clock);
    clock += workToFinish;
    remaining.set(currentJob, remaining.get(currentJob)! - workToFinish);

    if (remaining.get(currentJob)! === 0) {
      finish.set(currentJob, clock);
      currentJob = null;
    }
  }

  const missed = jobs.filter(
    (job) => finish.get(job.name as string)! > (job.due as number),
  );

  if (missed.length === 0) {
    return "";
  }

  missed.sort(
    (a, b) =>
      (a.due as number) - (b.due as number) ||
      ((a.name as string) < (b.name as string) ? -1