function createAxeRuleResultArtifact(result) {
  // Simplify `nodes` and collect nodeDetails for each.
  const nodes = result.nodes.map(node => {
    const {target, failureSummary, element} = node;
    // TODO: with `elementRef: true`, `element` _should_ always be defined, but need to verify.
    // @ts-expect-error - getNodeDetails put into scope via stringification
    const nodeDetails = getNodeDetails(/** @type {HTMLElement} */ (element));

    /** @type {Set<HTMLElement>} */
    const relatedNodeElements = new Set();
    /** @param {import('axe-core/axe').ImpactValue} impact */
    const impactToNumber =
      (impact) => [null, 'minor', 'moderate', 'serious', 'critical'].indexOf(impact);
    const checkResults = [...node.any, ...node.all, ...node.none]
      // @ts-expect-error CheckResult.impact is a string, even though ImpactValue is a thing.
      .sort((a, b) => impactToNumber(b.impact) - impactToNumber(a.impact));
    for (const checkResult of checkResults) {
      for (const relatedNode of checkResult.relatedNodes || []) {
        /** @type {HTMLElement} */
        // @ts-expect-error - should always exist, just being cautious.
        const relatedElement = relatedNode.element;

        // Prevent overloading the report with way too many nodes.
        if (relatedNodeElements.size >= 3) break;
        // Should always exist, just being cautious.
        if (!relatedElement) continue;
        if (element === relatedElement) continue;

        relatedNodeElements.add(relatedElement);
      }
    }
    // @ts-expect-error - getNodeDetails put into scope via stringification
    const relatedNodeDetails = [...relatedNodeElements].map(getNodeDetails);

    return {
      target,
      failureSummary,
      node: nodeDetails,
      relatedNodes: relatedNodeDetails,
    };
  });

  // Ensure errors can be serialized over the protocol.
  /** @type {Error | undefined} */
  // @ts-expect-error - when rules throw an error, axe saves it here.
  // see https://github.com/dequelabs/axe-core/blob/eeff122c2de11dd690fbad0e50ba2fdb244b50e8/lib/core/base/audit.js#L684-L693
  const resultError = result.error;
  let error;
  if (resultError instanceof Error) {
    error = {
      name: resultError.name,
      message: resultError.message,
    };
  }

  return {
    id: result.id,
    impact: result.impact || undefined,
    tags: result.tags,
    nodes,
    error,
  };
}
@param {import('axe-core/axe').Result} result
@return {LH.Artifacts.AxeRuleResult}