{"record":{"id":"30548c6163402e85","repo":"koala73/worldmonitor","slug":"pagepath-dropped-its-frozen-intel-brief","errorCode":null,"errorMessage":"${pagePath} dropped its frozen intel brief","messagePattern":"(.+?) dropped its frozen intel brief","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/build-crawlable-corpus.mjs","lineNumber":3525,"sourceCode":"    }\n  }\n  if (rows.brief && typeof rows.brief.text === 'string' && rows.brief.text.trim()) {\n    // Anchor on first AND last content lines after stripping section titles,\n    // bullets, and emphasis markers. Every generated brief opens with the same\n    // boilerplate header, so the first line alone cannot catch a cross-country\n    // swap; markdown conversion means raw `**` and ISO titles never appear.\n    const contentLines = rows.brief.text.trim().split('\\n')\n      .map((line) => unwrapBriefEmphasisLine(line.trim()))\n      .filter(Boolean)\n      .filter((line) => !isBriefSectionHeader(line, { countryCode, countryName }))\n      .map((line) => line.replace(/^(?:[•\\-]\\s*|\\*\\s+)/, '').replace(/\\*\\*/g, ''));\n    const anchors = [contentLines[0], contentLines.at(-1)]\n      .filter((line, index, all) => line && all.indexOf(line) === index)\n      .map((line) => escapeHtml(line.slice(0, 120)));\n    const pageText = html.replace(/<[^>]+>/g, '');\n    for (const anchor of anchors) {\n      if (!pageText.includes(anchor)) {\n        throw new Error(`${pagePath} dropped its frozen intel brief`);\n      }\n    }\n  }\n  const briefSources = Array.isArray(rows.brief?.sources) ? rows.brief.sources : [];\n  for (const source of briefSources) {\n    if (typeof source?.url === 'string' && !html.includes(`href=\"${escapeHtml(source.url)}\"`)) {\n      throw new Error(`${pagePath} dropped frozen brief source ${source.url}`);\n    }\n  }\n  for (const event of rows.timeline || []) {\n    if (!html.includes(escapeHtml(event.title))) {\n      throw new Error(`${pagePath} dropped frozen timeline event ${event.title}`);\n    }\n    if (typeof event.occurredAt === 'string' && !html.includes(`datetime=\"${escapeHtml(event.occurredAt)}\"`)) {\n      throw new Error(`${pagePath} dropped the date of frozen timeline event ${event.title}`);\n    }\n  }\n}","sourceCodeStart":3507,"sourceCodeEnd":3543,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/scripts/build-crawlable-corpus.mjs#L3507-L3543","documentation":"The frozen-intel-brief anchor check strips all tags from the page HTML and requires the brief's first and last content lines (first 120 chars, HTML-escaped, deduplicated) to appear verbatim in the resulting page text. If either anchor is missing, the page dropped part of its frozen intel brief, so the build throws rather than publish a truncated or altered brief.","triggerScenarios":"Asserting a generated country page when the stripped page text no longer contains the brief's opening or closing content line. Triggered by truncation, entity/encoding drift, or a formatter that alters whitespace or punctuation in the brief's first or last line.","commonSituations":"A post-processing step truncates long pages; a later formatter escapes or unescapes entities differently (e.g. &amp; vs &) so the escaped anchor no longer matches; content rendered lazily or conditionally is missing from the static HTML; brief text edited after freezing without re-rendering the page.","solutions":["Regenerate the page so it includes the full frozen brief content","Fix the formatter/post-processor that alters the brief's first or last line (entity encoding, whitespace normalization, truncation)","Verify the frozen brief and the page HTML are from the same build output; rebuild if stale","Check that nothing (styles, lazy loading, conditional rendering) removes the brief from the emitted static HTML"],"exampleFix":"// before: formatter re-escapes entities after validation\nconst html = escapeAll(revalidate(html));\n// after: run all transformations first, then validate\nconst html = escapeAll(html);\nassertFrozenBriefAnchors({ pagePath, html, rows });","handlingStrategy":"validation","validationCode":"const pageText = html.replace(/<[^>]+>/g, '');\nfor (const line of briefContentLines(brief)) {\n  if (!pageText.includes(escapeHtml(line.slice(0, 120)))) {\n    throw new Error(`${pagePath}: brief line missing from page text: ${line.slice(0, 40)}...`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  assertFrozenBriefAnchors({ pagePath, html, rows });\n} catch (err) {\n  if (err.message.includes('dropped its frozen intel brief')) {\n    console.error(`Brief content altered or truncated for ${pagePath}; diff the rendered page against the frozen brief`);\n  }\n  throw err;\n}","preventionTips":["Treat the frozen brief as immutable after publish-time validation; no formatter may run afterward","Run all entity/whitespace-normalizing formatters BEFORE anchor validation, not after","Keep briefs short enough that truncation middleware cannot cut them","Add a CI diff check between frozen brief content and rendered page text"],"tags":["build","html","content-integrity"],"backgroundTag":"internal-invariant-violation","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"}