```ts
export function replayRingLog(capacity: number, policy: string, operations: string[][]): { contents: string[]; journal: string[]; lost: number } {
  if (!Number.isInteger(capacity) || capacity <= 0) throw new Error('Invalid capacity');
  if (policy !== 'overwrite' && policy !== 'refuse') throw new Error('Invalid policy');
  if (!Array.isArray(operations)) throw new Error('Invalid operations');

  const contents: string[] = [];
  const journal: string[] = [];
  let lost = 0;

  for (const op of operations) {
    if (!Array.isArray(op) || op.length < 1) throw new Error('Invalid operation');
    const name = op[0];
    switch (name) {
      case 'push':
        if (op.length !== 2 || typeof op[1] !== 'string' || !op[1].trim()) throw new Error('Invalid push operation');
        if (contents.length < capacity) {
          contents.push(op[1]);
          journal.push(`stored ${op[1]}`);
        } else if (policy === 'overwrite') {
          const evicted = contents.shift();
          contents.push(op[1]);
          journal.push(`evicted ${evicted}, stored ${op[1]}`);
          lost++;
        } else {
          journal.push('refused');
        }
        break;
      case 'pop':
        if (contents.length > 0) {
          const removed = contents.shift();
          journal.push(`took ${removed}`);
        } else {
          journal.push('bare');
        }
        break;
      case 'peek':
        if (contents.length > 0) {
          journal.push(`front ${contents[0]}`);
        } else {
          journal.push('bare');
        }
        break;
      default:
        throw new Error('Invalid operation name');
    }
  }

  return { contents, journal, lost };
}
```