{"record":{"id":"c6cb7c0e892c37af","repo":"koala73/worldmonitor","slug":"is-missing-the-evaluation-section","errorCode":null,"errorMessage":" is missing the evaluation section","messagePattern":" is missing the evaluation section","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/build-comparison-pages.mjs","lineNumber":474,"sourceCode":"    if (faqNames.has(key)) {\n      throw new Error(page.slug + ' duplicate FAQ question: ' + question);\n    }\n    faqNames.add(key);\n  }\n  const merged = { ...page, ...narrative, faqs };\n  delete merged.extraFaqs;\n  const whyBody = (merged.whyWeWinBody ?? []).join(' ').replace(/\\s+/g, ' ').trim();\n  if (!whyBody) {\n    throw new Error(page.slug + ' is missing whyWeWinBody');\n  }\n  if (whyBody === merged.whyWeWin.replace(/\\s+/g, ' ').trim()) {\n    throw new Error(page.slug + ' whyWeWinBody must not repeat whyWeWin');\n  }\n  if (merged.heading && !(merged.headingProse?.length || merged.competitorProfiles?.length)) {\n    throw new Error(page.slug + ' H2 \"' + merged.heading + '\" has no following prose');\n  }\n  if (!merged.evaluationHeading || !merged.evaluationProse?.length) {\n    throw new Error(page.slug + ' is missing the evaluation section');\n  }\n  if (!merged.switchHeading || !merged.switchProse?.length) {\n    throw new Error(page.slug + ' is missing the switch-trigger section');\n  }\n  if (!merged.methodologyProse?.length) {\n    throw new Error(page.slug + ' is missing methodology prose');\n  }\n  return merged;\n}\n\nexport const COMPARISON_PAGES = COMPARISON_PAGE_SEEDS.map(applyComparisonNarrative);\n\nfunction renderParagraphs(paragraphs, escapeHtml) {\n  return (paragraphs ?? []).map((paragraph) => '      <p>' + escapeHtml(paragraph) + '</p>');\n}\n\nfunction renderHeadingSection(heading, paragraphs, escapeHtml, label) {\n  if (!heading) return [];","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/build-comparison-pages.mjs#L456-L492","documentation":"applyComparisonNarrative enforces that each comparison page has an evaluation section: a truthy evaluationHeading plus a non-empty evaluationProse array. The section is a mandatory SEO/content block; its absence fails the build.","triggerScenarios":"Running the build when a slug's merged narrative has no evaluationHeading (empty/undefined) or evaluationProse is missing/empty.","commonSituations":"Creating a new narrative entry and skipping the evaluation section template; a copy edit that removed the prose; misspelled keys (evalutationHeading, evaluationProse vs evaluationParagraphs).","solutions":["Add evaluationHeading and a non-empty evaluationProse array to the slug's narrative.","Check key spelling in the narrative object.","Restore any evaluation prose removed during copy editing.","Copy the evaluation section shape from an existing passing narrative as a template."],"exampleFix":"// before\n'worldmonitor-vs-x': { heading: '...', switchHeading: '...' }\n// after\n'worldmonitor-vs-x': {\n  heading: '...',\n  evaluationHeading: 'How we evaluated',\n  evaluationProse: ['We compared coverage, update frequency and pricing across both tools.'],\n}","handlingStrategy":"validation","validationCode":"if (!narrative.evaluationHeading || !narrative.evaluationProse?.length) {\n  throw new Error(page.slug + ' missing evaluation section');\n}","typeGuard":"const hasEvaluation = (n) => typeof n.evaluationHeading === 'string' && n.evaluationHeading.trim() !== '' && Array.isArray(n.evaluationProse) && n.evaluationProse.length > 0;","tryCatchPattern":"try {\n  page = applyComparisonNarrative(page);\n} catch (e) {\n  if (String(e.message).includes('missing the evaluation section')) {\n    console.error('Add evaluationHeading + evaluationProse for:', e.message);\n  } else throw e;\n}","preventionTips":["Start new narratives from a template containing all mandatory sections.","Keep a per-slug content checklist (evaluation, switch, methodology) in the authoring docs.","Run the build locally before committing narrative edits."],"tags":["build-time","content-validation","missing-content"],"backgroundTag":"empty-required-field","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}