```ts
/** How far apart two people stand in a register of forebears. */
export function kinshipDegree(
  register: Record<string, string[]>,
  one: string,
  other: string,
): Record<string, unknown> {
  // Validate the register
  if (typeof register !== "object" || Array.isArray(register) || register === null) {
    throw new Error("Register must be a non-null object.");
  }

  const validateName = (name: string | undefined, context: string) => {
    if (typeof name !== "string" || name.trim() === "") {
      throw new Error(`${context} must be a non-empty string.`);
    }
  };

  for (const [name, forebears] of Object.entries(register)) {
    validateName(name, `Key in register`);
    if (!Array.isArray(forebears) || forebears.length > 2) {
      throw new Error(`Forebear list for ${name} must be an array with 0 to 2 elements.`);
    }
    const uniqueForebears = new Set<string>();
    for (const forebear of forebears) {
      validateName(forebear, `Forebear of ${name}`);
      if (forebear === name) {
        throw new Error(`Person cannot be their own forebear (${name}).`);
      }
      if (!register[forebear]) {
        throw new Error(`Forebear ${forebear} of ${name} is not a key in the register.`);
      }
      if (!uniqueForebears.add(forebear)) {
        throw new Error(`Duplicate forebear ${forebear} for ${name}.`);
      }
    }
  }

  // Validate the input names
  validateName(one, `First person's name`);
  validateName(other, `Second person's name`);

  if (!(one in register) || !(other in register)) {
    throw new Error(`Both persons must be keys in the register.`);
  }

  const climb = (start: string): Map<string, number> => {
    const seen = new Map<string, number>();
    let frontier = [start];
    let step = 0;
    while (frontier.length > 0) {
      const next: string[] = [];
      for (const name of frontier) {
        if (!seen.has(name)) {
          seen.set(name, step);
          const parents = register[name] ?? [];
          for (const parent of parents) {
            if (!next.includes(parent)) {
              next.push(parent);
            }
          }
        }
      }
      frontier = next;
      step += 1;
    }
    return seen;
  };

  const mine = climb(one);
  const theirs = climb(other);

  // Direct line check
  if (mine.has(other) || theirs.has(one)) {
    const elder = mine.has(other) ? one : other;
    const steps = Math.abs(mine.get(other) ?? 0 - theirs.get(one) ?? 0);
    return { steps, line: "direct", meet: elder };
  }

  // Collateral line check
  let minSteps = Infinity;
  let meetingPoint = "";

  for (const [name, up] of mine) {
    const down = theirs.get(name);
    if (down !== undefined) {
      const totalSteps = up + down;
      if (
        totalSteps < minSteps ||
        (totalSteps === minSteps && name < meetingPoint)
      ) {
        minSteps = totalSteps;
        meetingPoint = name;
      }
    }
  }

  if (meetingPoint !== "") {
    return { steps: minSteps, line: "collateral", meet: meetingPoint };
  }

