```ts
/** Replay tile requests against a size-limited cache of fresh renders. */
export function tileRenders(requests: [number, string][], freshFor: number, size: number): [number, string][] {
  if (!Number.isInteger(freshFor) || freshFor < 1 || !Number.isInteger(size) || size < 1) {
    throw new Error("freshFor and size must be positive integers");
  }
  const held = new Map<string, number>();
  const renders: [number, string][] = [];
  for (const [tick, name] of requests) {
    if (held.has(name)) {
      const lastTick = held.get(name)!;
      if (tick >= lastTick && tick < lastTick + freshFor) {
        continue; // Serve still-fresh render
      }
    }
    if (held.size === size) {
      let oldestTile: [string, number] | null = null;
      for (const [tileName, tileTick] of held.entries()) {
        if (!oldestTile || tileTick < oldestTile[1] || (tileTick === oldestTile[1] && tileName < oldestTile[0])) {
          oldestTile = [tileName, tileTick];
        }
      }
      if (oldestTile) {
        held.delete(oldestTile[0]);
      }
    }
    held.set(name, tick);
    renders.push([tick, name]);
  }
  return renders;
}
```