```ts
/** The term mark built from weighted strands with discards. */
export function strandMarkSheet(
  strands: Array<Record<string, unknown>>
): Record<string, unknown> {
  if (strands.length === 0) {
    throw new Error("Empty report");
  }

  const strandNames = new Set<string>();
  let totalShare = 0;

  for (const strand of strands) {
    if (!strand.name || typeof strand.name !== "string" || strand.name.trim() === "") {
      throw new Error("Invalid strand name");
    }
    if (strandNames.has(strand.name)) {
      throw new Error("Repeated strand name");
    }
    strandNames.add(strand.name);

    if (typeof strand.share !== "number" || strand.share < 0 || !Number.isInteger(strand.share) || strand.share % 10 !== 0) {
      throw new Error("Invalid share");
    }
    totalShare += strand.share;

    if (typeof strand.discard !== "number" || strand.discard < 0 || !Number.isInteger(strand.discard)) {
      throw new Error("Invalid discard count");
    }

    if (!Array.isArray(strand.work) || strand.work.length === 0) {
      throw new Error("No work in strand");
    }

    for (const entry of strand.work) {
      if (!Array.isArray(entry) || entry.length !== 2) {
        throw new Error("Invalid work entry");
      }
      const score = entry[0];
      const availability = entry[1];

      if (typeof availability !== "number" || availability <= 0 || !Number.isInteger(availability)) {
        throw new Error("Invalid availability");
      }

      if (score !== "absent") {
        if (typeof score !== "number" || score < 0 || score > availability) {
          throw new Error("Invalid score");
        }
      }
    }
  }

  if (totalShare !== 1000) {
    throw new Error("Shares do not sum to 1000");
  }

  const discarded: string[] = [];
  let mark = 0;

  for (const strand of strands) {
    const work = strand.work as [number | "absent", number][];
    const order = work.map((_entry, index) => index);
    order.sort((a, b) => {
      const scoreA = work[a][0] === "absent" ? 0 : work[a][0];
      const scoreB = work[b][0] === "absent" ? 0 : work[b][0];
      if (scoreA * work[b][1] !== scoreB * work[a][1]) {
        return scoreA * work[b][1] - scoreB * work[a][1];
      }
      return work[b][1] - work[a][1];
    });
    const dropped = order.slice(0, strand.discard);
    for (const index of dropped) {
      discarded.push(strand.name + "#" + index);
    }
    let scored = 0;
    let available = 0;
    work.forEach((entry, index) => {
      if (dropped.includes(index) || entry[0] === "absent") {
        return;
      }
      scored += entry[0];
      available += entry[1];
    });
    mark += Math.floor((strand.share * scored) / available);
  }

  return { mark, discarded };
}
```