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

  1. Rewrite each listed phrase in the CV source (cv.md) to a direct, factual statement
  2. Regenerate the PDF and confirm the warning disappears
  3. 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

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


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)