santifer/career-ops · warning

Possible duplicates: `).join(', ')} ( — )

Error message

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

What it means

A warning from verify-pipeline.mjs's duplicate check (Check 2): two or more tracker entries in applications.md share the same normalized company+role key (normalizeTextKey on both fields). Exact-string duplicates usually mean the same opening was added twice — the AGENTS.md rule forbids new entries when company+role already exists; update the existing row instead.

Solutions

  1. Run `node dedup-tracker.mjs` to remove exact duplicates automatically.
  2. Decide which row is canonical and update it via `node set-status.mjs <report#> <State> --note ...`; delete the redundant row.
  3. For genuinely distinct openings with near-identical titles, add the req/posting ID to the notes of both rows (`req JR-10423`) so merge-tracker.mjs treats them as distinct.
  4. Prevent recurrence: never hand-edit applications.md; write batch/tracker-additions/*.tsv and run `node merge-tracker.mjs` after each batch.

Example fix

// before: second hand-added row duplicates row 42
| 43 | 2026-09-16 | Acme | Senior Backend Eng | ... |
// after: update the existing row instead
node set-status.mjs 42 Applied --note "applied 2026-09-16"
Defensive patterns

Strategy: validation

Validate before calling

const key = normalizeTextKey(company) + '::' + normalizeTextKey(role);
if (existingKeys.has(key)) updateExistingRow(existingRowNum) else appendRow();

Prevention

When it happens

Trigger: Running `node verify-pipeline.mjs` when the tracker contains two rows whose lowercased/normalized company and role strings are identical, e.g. after hand-editing applications.md or merging without merge-tracker.mjs dedup.

Common situations: Manually appending rows instead of writing TSVs to batch/tracker-additions/; two parallel batch workers both adding the same offer; same role posted at different URLs not distinguished by req ID in notes; copy-pasting an existing row to change its status.

Related errors


AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16). Data as JSON: /api/errors/60f501af545e1fe9. Report an issue: GitHub.

Appendix: source

Thrown at verify-pipeline.mjs:167

    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 e7abd431fc)