```ts
/**
 * Sorts shelf marks according to the Marrow scheme rules.
 * @param marks - An array of shelf mark strings to sort.
 * @returns A new array of sorted shelf mark strings.
 */
export function orderShelfMarks(marks: string[]): string[] {
  if (!Array.isArray(marks) || marks.length === 0) {
    throw new Error("Input must be a non-empty array of strings.");
  }

  const regex = /^[A-Z]{1,3} (\d{1,4}(?:\.\d+)?)( [a-z]\d{1,3})$/;

  const parsedMarks: { original: string; stack: string; run: number; cutter: string }[] = [];

  for (const mark of marks) {
    if (typeof mark !== "string") {
      throw new Error("All entries must be strings.");
    }

    const match = mark.match(regex);
    if (!match) {
      throw new Error(`Invalid shelf mark format: ${mark}`);
    }

    const stack = match[1];
    const runStr = match[2];
    const cutter = match[3];

    const runParts = runStr.split(".");
    const wholePart = parseInt(runParts[0], 10);
    const decimalPart = runParts.length > 1 ? parseFloat(`0.${runParts[1]}`) : 0;

    parsedMarks.push({
      original: mark,
      stack,
      run: wholePart + decimalPart,
      cutter
    });
  }

  if (new Set(parsedMarks.map(mark => mark.original)).size !== marks.length) {
    throw new Error("Duplicate shelf marks are not allowed.");
  }

  parsedMarks.sort((a, b) => {
    if (a.stack !== b.stack) {
      return a.stack.localeCompare(b.stack);
    }
    if (a.run !== b.run) {
      return a.run - b.run;
    }
    return a.cutter.localeCompare(b.cutter);
  });

  return parsedMarks.map(mark => mark.original);
}
```