{"record":{"id":"fac2a2f0bd5c314c","repo":"koala73/worldmonitor","slug":"is-missing-methodology-prose","errorCode":null,"errorMessage":" is missing methodology prose","messagePattern":" is missing methodology prose","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/build-comparison-pages.mjs","lineNumber":480,"sourceCode":"  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 [];\n  const body = renderParagraphs(paragraphs, escapeHtml);\n  if (body.length === 0) {\n    throw new Error((label || heading) + ' is missing following prose');\n  }\n  return ['      <h2>' + escapeHtml(heading) + '</h2>', ...body];\n}","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/build-comparison-pages.mjs#L462-L498","documentation":"build-comparison-pages.mjs applies narrative content to comparison page seeds via applyComparisonNarrative. It validates that each merged page has an evaluation section, a switch-trigger section, and methodology prose. If a page's methodologyProse array is empty or undefined, the build fails with '<slug> is missing methodology prose' so no comparison page ships without required methodology content.","triggerScenarios":"Calling applyComparisonNarrative (directly or via COMPARISON_PAGES construction at module load) with a seed whose merged narrative has no methodologyProse array, or methodologyProse set to [] / null.","commonSituations":"Adding a new COMPARISON_PAGE_SEEDS entry without copying the full narrative block from an existing seed; a content edit accidentally deleting the methodologyProse key; a merge/override object that replaces narrative fields and drops methodologyProse.","solutions":["Add a non-empty methodologyProse array (strings of paragraph text) to the affected page's seed in COMPARISON_PAGE_SEEDS.","If the page uses a narrative override/merge source, ensure the merge output includes methodologyProse rather than replacing it with undefined.","Run the build script to confirm the slug named in the message now passes applyComparisonNarrative."],"exampleFix":"// before\n{\n  slug: 'country-instability-index-alternatives',\n  methodologyProse: [],\n}\n// after\n{\n  slug: 'country-instability-index-alternatives',\n  methodologyProse: [\n    'World Monitor derives its index from N providers, weighted by ...',\n  ],\n}","handlingStrategy":"validation","validationCode":"if (!Array.isArray(page.methodologyProse) || page.methodologyProse.length === 0) {\n  throw new Error(`${page.slug}: methodologyProse must be a non-empty array before building`);\n}","typeGuard":"const hasProse = (v) => Array.isArray(v) && v.length > 0 && v.every((p) => typeof p === 'string' && p.trim() !== '');","tryCatchPattern":null,"preventionTips":["Copy an existing seed's full narrative shape when adding new comparison pages.","Add a unit test that maps COMPARISON_PAGE_SEEDS and asserts every required prose array is non-empty."],"tags":["build","content-validation","comparison-pages"],"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"}