{"record":{"id":"9683de02375813ec","repo":"santifer/career-ops","slug":"cv-is-pagecount-actuallabel-the-allowed-max","errorCode":null,"errorMessage":"CV is ${pageCount} ${actualLabel}; the allowed maximum is ${maxPages} ${allowedLabel}. Trim lower-priority bullets, older roles, secondary projects, or the competencies strip, then regenerate. (--strict-pages requested)","messagePattern":"CV is (.+?) (.+?); the allowed maximum is (.+?) (.+?)\\. Trim lower-priority bullets, older roles, secondary projects, or the competencies strip, then regenerate\\. \\(--strict-pages requested\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"generate-pdf.mjs","lineNumber":301,"sourceCode":" * @returns {void}\n */\nexport function enforcePageBudget(pageCount, { maxPages = 2, strictPages = false } = {}) {\n  if (!Number.isInteger(pageCount) || pageCount < 1) {\n    throw new Error(`Could not determine the rendered PDF page count (received ${pageCount}).`);\n  }\n  if (!Number.isInteger(maxPages) || maxPages < 1) {\n    throw new Error(`Invalid page budget \"${maxPages}\". Use a positive integer.`);\n  }\n  if (pageCount <= maxPages) return;\n\n  const actualLabel = 'pages';\n  const allowedLabel = maxPages === 1 ? 'page' : 'pages';\n  const message =\n    `CV is ${pageCount} ${actualLabel}; the allowed maximum is ${maxPages} ${allowedLabel}. ` +\n    'Trim lower-priority bullets, older roles, secondary projects, or the competencies strip, then regenerate.';\n\n  if (strictPages) {\n    throw new Error(`${message} (--strict-pages requested)`);\n  }\n\n  console.warn(`⚠️  ${message} Continuing because overflow is warning-only by default; use --strict-pages to reject it.`);\n}\n\n/**\n * Read the page count from the PDF catalog's root /Pages dictionary.\n *\n * Following the catalog reference keeps page-like text in content streams or\n * metadata from being mistaken for an actual page object.\n *\n * @param {Buffer} pdfBuffer - PDF bytes returned by Chromium.\n * @returns {number}\n */\nfunction countRenderedPdfPages(pdfBuffer) {\n  const pdf = pdfBuffer.toString('latin1');\n  const objects = new Map();\n  const objectPattern = /(?:^|[\\r\\n])(\\d+)\\s+(\\d+)\\s+obj\\b([\\s\\S]*?)\\bendobj\\b/g;","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/generate-pdf.mjs#L283-L319","documentation":"Thrown by enforcePageBudget() in generate-pdf.mjs when strictPages is true and the rendered CV exceeds maxPages. Unlike the default warning-only path, --strict-pages turns overflow into a hard failure so CI/batch runs reject over-budget CVs. The message tells you exactly what to trim (lower-priority bullets, older roles, secondary projects, the competencies strip).","triggerScenarios":"Running generate-pdf with --strict-pages (or strictPages:true) on a CV whose rendered page count is greater than maxPages (default 2). pageCount > maxPages AND strictPages === true.","commonSituations":"CI gate rejecting a CV that grew past 2 pages after adding a new role; a batch run with strictPages enabled on a dense senior CV; maxPages lowered from 2 to 1 without trimming content.","solutions":["Trim content per the message: cut lower-priority bullets, oldest roles, secondary projects, or the competencies strip, then regenerate.","Raise maxPages if the role genuinely warrants it: generate-pdf --max-pages 3 --strict-pages.","Drop --strict-pages locally to get a warning-only run while you iterate, then re-enable for the final gate.","Use the pdf mode's content-selection flags to deprioritize older sections instead of editing cv.md destructively."],"exampleFix":"// before\nenforcePageBudget(count, { maxPages: 2, strictPages: true });\n// 3-page CV throws\n\n// after — raise budget for senior roles\nenforcePageBudget(count, { maxPages: 3, strictPages: true });\n// or remove strict for warning-only iteration\nenforcePageBudget(count, { maxPages: 2, strictPages: false });","handlingStrategy":"validation","validationCode":"null","typeGuard":null,"tryCatchPattern":"try {\n  enforcePageBudget(count, { maxPages, strictPages: true });\n} catch (e) {\n  if (e.message.includes('--strict-pages')) {\n    // over-budget in strict mode: surface to CI, request content trim or budget bump\n    core.setFailed(e.message);\n  } else throw e;\n}","preventionTips":["Use --strict-pages in CI/release gates and warning-only during local iteration.","Keep senior CVs within budget by maintaining a 'competencies strip' and dated roles that can be dropped.","If a role genuinely needs more pages, raise maxPages explicitly rather than disabling strict.","Run generate-pdf once non-strict to preview count before enabling the gate."],"tags":["pdf","configuration","validation","ci-gate"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}