{"record":{"id":"19959fb17664a7ce","repo":"santifer/career-ops","slug":"advisory-phrase-phrase","errorCode":null,"errorMessage":"  - advisory phrase: ${phrase}","messagePattern":"  - advisory phrase: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"generate-pdf.mjs","lineNumber":1364,"sourceCode":"  if (!skipFactCheck && cvMarkdown) {\n    // Imported lazily, INSIDE the guard. A static import is resolved at module\n    // load whether or not this branch runs, and the page-budget/batch suites copy\n    // generate-pdf.mjs alone into a temp workspace — a static import of a sibling\n    // that isn't copied made every one of those suites die with\n    // ERR_MODULE_NOT_FOUND before reaching the behaviour under test. Those\n    // fixtures also ship no cv.md, so this branch is never entered there. If the\n    // module is genuinely missing in a real workspace this throws and the render\n    // fails, which is the correct direction to fail for a fact gate.\n    const { assertFacts } = await import('./verify-cv-facts.mjs');\n    const factCheck = assertFacts(html, { label: basename(inputPath) });\n    // Ahead of the verdict, because it qualifies it: with no config the phrase\n    // lists are empty, so a \"passed\" below covers metrics and facts only.\n    if (factCheck.configMissing) {\n      console.warn('⚠️  No config/cv-facts.json — forbidden/advisory phrase checks did not run.');\n    }\n    if (factCheck.verdict === 'warn') {\n      console.warn(`⚠️  CV fact check warning: ${basename(inputPath)}`);\n      for (const phrase of factCheck.warnings) console.warn(`  - advisory phrase: ${phrase}`);\n    } else {\n      console.log('✅ Fact check passed');\n    }\n  }\n\n  return renderHtmlToPdf(html, outputPath, {\n    format,\n    baseDir: dirname(inputPath),\n    reportNum,\n    inputPath,\n    maxPages,\n    strictPages,\n    styleTokens: readStyleTokens(resolve(workspaceRoot, 'config', 'profile.yml')),\n  });\n}\n\n/**\n * Drive batch mode (#2384) from a JSON manifest.","sourceCodeStart":1346,"sourceCodeEnd":1382,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/generate-pdf.mjs#L1346-L1382","documentation":"The detail line emitted by the same fact-check pass in generate-pdf.mjs: for each phrase that triggered the 'warn' verdict, it prints '  - advisory phrase: <phrase>'. It is informational output enumerating exactly which advisory phrases were found in the CV text.","triggerScenarios":"Always paired with error 540: factCheck.verdict === 'warn' and factCheck.warnings is non-empty; the loop prints one such line per advisory phrase match.","commonSituations":"Reviewing PDF generation output to find hedged or risky wording ('maybe', 'assisted', passive hedges) before shipping a CV.","solutions":["Rewrite each listed phrase in the CV source (cv.md) to a direct, factual statement","Regenerate the PDF and confirm the warning disappears","Tune the advisory phrase list in config/cv-facts.json if it over-flags legitimate wording"],"exampleFix":"// before\n\"responsible for helping the team achieve...\"\n// after\n\"Led a 4-person team that shipped X on schedule\"","handlingStrategy":"validation","validationCode":"const banned = config.advisoryPhrases || [];\nconst hits = banned.filter(p => cvText.includes(p));\nif (hits.length) throw new Error('Advisory phrases present: ' + hits.join(', '));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Search cv.md for each advisory phrase before committing edits","Keep the advisory list small and reviewed so warnings stay actionable","Re-render and confirm zero advisory lines before sending a CV"],"tags":["cv","fact-check","advisory-phrase","console-warning"],"backgroundTag":"schema-validation-failed","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}