santifer/career-ops · warning

cv.md not found — cannot add to a CV that does not exist

Error message

cv.md not found — cannot add to a CV that does not exist

What it means

Emitted by Check 11 of verify-pipeline.mjs. Each tracker row's Company cell is tested against CONFIDENTIAL_WORD_RE — confidential, vertraulich, confidentiel, confidencial, riservato, gizli, 機密, سري. A match means a locale-dependent confidentiality word was typed as the company name; the data contract requires the locale-invariant structural marker '?' instead, because such words can collide with a real firm name (a company actually called 'Confidential') and defeat exact string matching and dedup keys.

Source

Thrown at add-entry.mjs:181

 * contents and a per-target status. No I/O — this is what the tests exercise.
 * @returns {{ cv: string, articleDigest: string, result: object }}
 */
export function applyAdd(payload, { cvText = null, articleText = null } = {}) {
  if (!payload || typeof payload !== 'object' || (!payload.cv && !payload.articleDigest)) {
    throw new Error('payload must include at least one of: cv, articleDigest');
  }

  const result = {};
  let cv = cvText;
  let articleDigest = articleText;

  if (payload.cv) {
    const { section, dedupKey, entry } = payload.cv;
    if (!section || !entry) throw new Error('payload.cv requires { section, entry }');
    // dedupKey is what makes the insert idempotent — refuse to add without one
    // rather than silently allowing duplicate re-runs.
    if (!normalizeKey(dedupKey)) throw new Error('payload.cv requires a non-empty dedupKey (used for dedup/idempotency)');
    if (cvText === null) throw new Error(`cv.md not found — cannot add to a CV that does not exist`);
    if (cvHasEntry(cvText, section, dedupKey)) {
      result.cv = { status: 'duplicate', section };
    } else {
      cv = insertIntoCvSection(cvText, section, entry);
      result.cv = { status: 'added', section };
    }
  }

  if (payload.articleDigest) {
    const { dedupKey, entry } = payload.articleDigest;
    if (!entry) throw new Error('payload.articleDigest requires { entry }');
    if (!normalizeKey(dedupKey)) throw new Error('payload.articleDigest requires a non-empty dedupKey (used for dedup/idempotency)');
    // article-digest.md is optional; create it from a header when missing.
    const current = articleText === null
      ? '# Article Digest -- Proof Points\n\nCompact proof points from portfolio projects. Read by career-ops at evaluation time.\n'
      : articleText;
    if (articleDigestHasEntry(current, dedupKey)) {
      result.articleDigest = { status: 'duplicate' };

View on GitHub (pinned to 60398d6549)

Solutions

  1. Replace the Company cell with the structural marker '?'
  2. Record the agency in the Via column — add it first with `node merge-tracker.mjs --migrate-via` if the tracker lacks it; '?' with no Via channel is the error-level sibling finding
  3. Once the end employer becomes known, replace '?' with the real company name

Example fix

// before:
| 17 | 2026-02-10 | Confidential | Backend Engineer | Applied | ... |

// after:
| 17 | 2026-02-10 | ? | Backend Engineer | Applied | ... | via=Hays recorded in Via |
Defensive patterns

Strategy: type-guard

Validate before calling

// Run BEFORE writing a Company cell: reject locale-dependent placeholder words.
const CONFIDENTIAL_WORD_RE = /^(confidential|vertraulich|confidentiel|confidencial|riservato|gizli|機密|سري)$/i;
export function validCompanyCell(company) {
  const c = String(company ?? '').trim();
  return c !== '' && !CONFIDENTIAL_WORD_RE.test(c);
}

Type guard

const CONFIDENTIAL_WORD_RE = /^(confidential|vertraulich|confidentiel|confidencial|riservato|gizli|機密|سري)$/i;
// Structural unknown-employer marker: locale-invariant, cannot collide with a real firm.
const isStructuralUnknownEmployer = (company) => String(company ?? '').trim() === '?';
const isSafeCompanyCell = (company) => isStructuralUnknownEmployer(company) || !CONFIDENTIAL_WORD_RE.test(String(company ?? '').trim());

Prevention

When it happens

Trigger: Adding a tracker row by hand from an agency email that says 'Confidential client' and typing that into the Company cell; importing rows localized for the DACH ('Vertraulich'), Japanese ('機密'), or Arabic ('سري') market mode sets.

Common situations: Agency-mediated applications where the end employer is hidden; localizing the tracker into another market's vocabulary; copy-pasting the subject line of a blind recruiter email.

Related errors


AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20). Data as JSON: /api/errors/79421732be2e3a22. Report an issue: GitHub.