santifer/career-ops · warning

⚠️ Non-canonical status "${status}" → defaulting to "Evalua

Error message

⚠️  Non-canonical status "${status}" → defaulting to "Evaluated"

What it means

validateStatus() in merge-tracker.mjs normalizes tracker status cells: it lowercases, maps known aliases (English, Spanish forms, DUPLICADO/repost patterns) to canonical states from templates/states.yml. Anything unrecognized falls back to 'Evaluated' with this warning — a deliberately conservative default that keeps the row mergeable while flagging the typo.

Source

Thrown at merge-tracker.mjs:181

    // Spanish → English
    'evaluada': 'Evaluated', 'condicional': 'Evaluated', 'hold': 'Evaluated', 'evaluar': 'Evaluated', 'verificar': 'Evaluated',
    'aplicado': 'Applied', 'enviada': 'Applied', 'aplicada': 'Applied', 'applied': 'Applied', 'sent': 'Applied',
    'respondido': 'Responded',
    'entrevista': 'Interview',
    'oferta': 'Offer',
    'rechazado': 'Rejected', 'rechazada': 'Rejected',
    'contratado': 'Hired', 'contratada': 'Hired', 'accepted': 'Hired', 'accept': 'Hired',
    'descartado': 'Discarded', 'descartada': 'Discarded', 'cerrada': 'Discarded', 'cancelada': 'Discarded',
    'no aplicar': 'SKIP', 'no_aplicar': 'SKIP', 'skip': 'SKIP', 'monitor': 'SKIP',
    'geo blocker': 'SKIP',
  };

  if (aliases[lower]) return aliases[lower];

  // DUPLICADO/Repost → Discarded
  if (/^(duplicado|dup|repost)/i.test(lower)) return 'Discarded';

  console.warn(`⚠️  Non-canonical status "${status}" → defaulting to "Evaluated"`);
  return 'Evaluated';
}

// normalizeVia (Unicode-aware Via/agency key, #1596/#1603) lives in
// tracker-parse.mjs so merge-tracker and analyze-patterns share ONE normalizer
// and agency identity can't drift between scripts. (normalizeCompany lives in
// tracker-utils.mjs since #1460 so every tracker writer shares one company key.)

/**
 * Extract the bracketed report number from a Markdown report link.
 *
 * Report-number equality is an exact duplicate signal, but only after company
 * equality is confirmed by the caller. This helper reads links such as
 * `[123](../reports/123-company-role-date.md)` and returns the numeric id.
 *
 * Layouts whose header has no dedicated Report column (e.g. a customized
 * `… | Materials | Apply Link | Follow-up | Notes` shape) embed the link in
 * Notes prose instead (see buildRow), so the Notes cell is scanned as a

View on GitHub (pinned to 60398d6549)

Solutions

  1. Correct the status cell to a canonical state: Evaluated, Applied, Responded, Interview, Offer, Hired, Rejected, Discarded, or SKIP
  2. If the value is a legitimate new synonym, add it to the aliases map in merge-tracker.mjs and normalize existing rows with node normalize-statuses.mjs
  3. Run node verify-pipeline.mjs after merging to catch rows that landed on the wrong default

Example fix

# before (batch/tracker-additions/042-acme.tsv, status column)
042	2026-08-20	Acme	SRE	Interveiw	4.2/5	...

# after
042	2026-08-20	Acme	SRE	Interview	4.2/5	...
Defensive patterns

Strategy: validation

Validate before calling

const CANONICAL_STATES = new Set(['Evaluated','Applied','Responded','Interview','Offer','Hired','Rejected','Discarded','SKIP']);
function isCanonicalStatus(s) {
  return CANONICAL_STATES.has(String(s).trim());
}

Type guard

/** @param {unknown} s */
function isCanonicalTrackerStatus(s) {
  return typeof s === 'string' && CANONICAL_STATES.has(s.trim());
}

Prevention

When it happens

Trigger: A TSV/tracker cell in the status column containing a value outside the alias table — e.g. 'Interveiw', 'offer!', 'rejected (no fit)' — reaches the end of validateStatus() and is coerced to 'Evaluated'.

Common situations: Hand-written batch TSVs with typos; statuses copied from a company email ('withdrawn'); locale variants not in the alias map; trailing punctuation or markdown bold breaking the match.

Related errors


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