santifer/career-ops · warning

Possible duplicates: ${group.map(e => `#${e.num}`).join(', '

Error message

Possible duplicates: ${group.map(e => `#${e.num}`).join(', ')} (${group[0].company} — ${group[0].role})

What it means

verify-pipeline.mjs check 2 groups tracker rows by a normalized company::role key (Unicode-aware since #2393 -- an [a-z0-9] strip previously keyed every Japanese company/role to '' and flagged unrelated rows) and warns when a key has more than one row. 'Possible' because the project rule forbids duplicate company+role entries, yet genuinely distinct requisitions can legitimately share a title; the warning lists the row numbers so a human can judge.

Source

Thrown at verify-pipeline.mjs:162

    badStatuses++;
  }
}
if (badStatuses === 0) ok('All statuses are canonical');

// --- Check 2: Duplicates ---
const companyRoleMap = new Map();
let dupes = 0;
for (const e of entries) {
  // Unicode-aware (#2393): an [a-z0-9] strip erases non-Latin scripts outright,
  // so every Japanese company and every Japanese role keyed to '' and unrelated
  // rows were reported as "possible duplicates".
  const key = normalizeTextKey(e.company) + '::' + normalizeTextKey(e.role);
  if (!companyRoleMap.has(key)) companyRoleMap.set(key, []);
  companyRoleMap.get(key).push(e);
}
for (const [key, group] of companyRoleMap) {
  if (group.length > 1) {
    warn(`Possible duplicates: ${group.map(e => `#${e.num}`).join(', ')} (${group[0].company} — ${group[0].role})`);
    dupes++;
  }
}
if (dupes === 0) ok('No exact duplicates found');

// --- Check 3: Report links ---
// Markdown links resolve relative to the file that contains them, so report
// links must resolve against the tracker's own directory (see #760). For the
// transition we also accept legacy root-relative links: try the tracker dir
// first, then fall back to the repo root before flagging a link broken.
const TRACKER_DIR = dirname(APPS_FILE);
let brokenReports = 0;
for (const e of entries) {
  const match = e.report.match(/\]\(([^)]+)\)/);
  if (!match) continue;
  const link = match[1];
  if (!existsSync(join(TRACKER_DIR, link)) && !existsSync(join(CAREER_OPS, link))) {
    error(`#${e.num}: Report not found: ${link}`);

View on GitHub (pinned to 60398d6549)

Solutions

  1. If both rows are the same opening, collapse them: node dedup-tracker.mjs.
  2. If they are distinct requisitions, add the req/job/posting ID to both rows' notes (e.g. 'req JR-10423') so merge-tracker treats them as distinct (#1524) and the pairing is explainable.
  3. Keep each row's report link pointing at its own report file.

Example fix

# before: same title, indistinguishable rows
| 64 | ... | Acme | ML Engineer | ... | req JR-10423 |
| 71 | ... | Acme | ML Engineer | ... |              |
# after: both carry their requisition IDs (distinct openings, warning explainable)
| 64 | ... | Acme | ML Engineer | ... | req JR-10423 |
| 71 | ... | Acme | ML Engineer | ... | req JR-10501 |
Defensive patterns

Strategy: validation

Validate before calling

// Before writing a TSV, check the tracker for an existing company+role row
function normalizeKey(s) { return s.trim().toLowerCase().replace(/[\s–—-]+/g, ' '); }
const existing = entries.some(e =>
  normalizeKey(e.company) === normalizeKey(company) && normalizeKey(e.role) === normalizeKey(role));
if (existing && !reqId) throw new Error('company+role already tracked — update the row or add a req ID');

Prevention

When it happens

Trigger: Two TSVs merged for the same company+role (violating the never-duplicate rule); a reposted role re-applied and tracked twice; two distinct requisitions with identical titles but no distinguishing req/job ID in the notes column.

Common situations: Parallel workers independently evaluating the same posting; re-applying to a reposted job months later; leveled variants ('Engineer' vs 'Engineer II') that normalize to the same key.

Related errors


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