santifer/career-ops · info
- advisory phrase
Error message
- advisory phrase: ${phrase} What it means
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.
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
Example fix
// before "responsible for helping the team achieve..." // after "Led a 4-person team that shipped X on schedule"
Defensive patterns
Strategy: validation
Validate before calling
const banned = config.advisoryPhrases || [];
const hits = banned.filter(p => cvText.includes(p));
if (hits.length) throw new Error('Advisory phrases present: ' + hits.join(', ')); Prevention
- 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
When it happens
Trigger: Always paired with error 540: factCheck.verdict === 'warn' and factCheck.warnings is non-empty; the loop prints one such line per advisory phrase match.
Common situations: Reviewing PDF generation output to find hedged or risky wording ('maybe', 'assisted', passive hedges) before shipping a CV.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ⚠️ CV fact check warning
- ⚠️ No config/cv-facts.json — forbidden/advisory phrase…
- ⚠️ config/profile.yml cv.sections lists only
- ⚠️ config/profile.yml cv.sections lists
- ⚠️ config/profile.yml cv.sections lists
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/19959fb17664a7ce.
Report an issue: GitHub.
Appendix: source
Thrown at generate-pdf.mjs:1364
if (!skipFactCheck && cvMarkdown) {
// Imported lazily, INSIDE the guard. A static import is resolved at module
// load whether or not this branch runs, and the page-budget/batch suites copy
// generate-pdf.mjs alone into a temp workspace — a static import of a sibling
// that isn't copied made every one of those suites die with
// ERR_MODULE_NOT_FOUND before reaching the behaviour under test. Those
// fixtures also ship no cv.md, so this branch is never entered there. If the
// module is genuinely missing in a real workspace this throws and the render
// fails, which is the correct direction to fail for a fact gate.
const { assertFacts } = await import('./verify-cv-facts.mjs');
const factCheck = assertFacts(html, { label: basename(inputPath) });
// Ahead of the verdict, because it qualifies it: with no config the phrase
// lists are empty, so a "passed" below covers metrics and facts only.
if (factCheck.configMissing) {
console.warn('⚠️ No config/cv-facts.json — forbidden/advisory phrase checks did not run.');
}
if (factCheck.verdict === 'warn') {
console.warn(`⚠️ CV fact check warning: ${basename(inputPath)}`);
for (const phrase of factCheck.warnings) console.warn(` - advisory phrase: ${phrase}`);
} else {
console.log('✅ Fact check passed');
}
}
return renderHtmlToPdf(html, outputPath, {
format,
baseDir: dirname(inputPath),
reportNum,
inputPath,
maxPages,
strictPages,
styleTokens: readStyleTokens(resolve(workspaceRoot, 'config', 'profile.yml')),
});
}
/**
* Drive batch mode (#2384) from a JSON manifest.View on GitHub (pinned to aac998c7ed)