santifer/career-ops · warning
⚠️ Keep # and # : exact-title match but advanced status…
Error message
⚠️ Keep #${a.num} and #${b.num}: exact-title match but advanced status requires exact report identity What it means
dedup-tracker.mjs roleMatch() normally collapses two tracker rows with exact-title matches, but when either row already has an 'advanced' status (Interview, Offer, Hired, etc.), a merge would destroy process history. The function therefore refuses to merge and warns that both rows are kept unless they point to the exact same report identity.
Solutions
- Decide if the two rows are genuinely distinct openings — if yes, do nothing; the warning is correct behavior
- Add the req/posting ID to the notes of both rows so future merges can distinguish them (REQ_NUMBER_RE: 'req JR-10423', 'job id 88214', etc.)
- If they are truly duplicates with identical report links, verify the report identity matches so the guard allows merging
- If one row is stale, close it with set-status.mjs <num> Discarded instead of merging
Example fix
// before: two rows, same title, no req id, one in Interview | 12 | ... | Acme | Backend Engineer | Interview | ... | | 41 | ... | Acme | Backend Engineer | Evaluated | ... | // after: disambiguate with req IDs in notes | 12 | ... | Backend Engineer ... req JR-10423 | | 41 | ... | Backend Engineer ... req JR-20877 |
Defensive patterns
Strategy: validation
Validate before calling
// before running dedup-tracker, ensure same-title rows carry req IDs in notes
const rows = parseTracker();
const dupTitle = rows.filter(r => r.title === t);
const needsReqId = dupTitle.some(r => isAdvancedStatus(r.status)) && dupTitle.length > 1;
if (needsReqId) console.warn('add req/posting id to notes for', t); Type guard
const REQ_ID_RE = /\b(?:job id|posting id|requisition|req|jr|job|posting|ref|r_)\s*[A-Za-z]*\d/i; const hasReqId = (row) => REQ_ID_RE.test(row.notes ?? '');
Prevention
- Always put the req/posting ID in tracker notes when a company has multiple similar openings
- Never merge rows whose status has progressed past Evaluated without verifying identical report identity
- Review dedup-tracker output warnings before accepting any merge
When it happens
Trigger: Running `node dedup-tracker.mjs` over data/applications.md where two rows fuzzy/exact-match on title AND at least one status is advanced (isAdvancedStatus) AND the pair does not resolve to the identical report. roleMatch returns false and prints this warning once per pair (protected via protectedTitlePairs set).
Common situations: A company reposted the same role title in a new requisition while the old application already reached Interview; a scanner ingested the same title at two locations/req IDs; user re-applied to a role previously interviewed for.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- # : Score has markdown bold
- INVALID_DATE
- Possible duplicates: `).join(', ')} ( — )
- # : — no automatic update
- Conflicting status recommendations require manual review:
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/8813ae98ae640390.
Report an issue: GitHub.
Appendix: source
Thrown at dedup-tracker.mjs:231
*
* @param {object} a - First parsed applications.md row.
* @param {object} b - Second parsed applications.md row.
* @returns {boolean} True when dedup may cluster the two rows as duplicates.
*/
function roleMatch(a, b) {
if (sameReportIdentity(a, b)) return true;
if (normalizeRole(a.role) !== normalizeRole(b.role)) return false;
// Exact-title duplicates that have entered the real application pipeline are
// kept separate. A user may already have applied to one row; deleting it
// because a higher-scored exact-title sibling exists would lose status,
// report, and notes. Keep both unless the rows point to the exact same
// report identity.
if (isAdvancedStatus(a.status) || isAdvancedStatus(b.status)) {
const key = pairKey(a, b);
if (!protectedTitlePairs.has(key)) {
protectedTitlePairs.add(key);
console.warn(`⚠️ Keep #${a.num} and #${b.num}: exact-title match but advanced status requires exact report identity`);
}
return false;
}
return true;
}
/**
* Parse a tracker score cell into a numeric value for keeper selection.
*
* Scores may include Markdown bolding or a `/5` suffix. Dedup only needs the
* numeric part so it can keep the highest-scored duplicate row in a cluster.
*
* @param {string} s - Raw score cell such as `4.3/5` or `**4.3/5**`.
* @returns {number} Parsed score, or 0 when no number is present.
*/
function parseScore(s) {
const m = s.replace(/\*\*/g, '').match(/([\d.]+)/);View on GitHub (pinned to aac998c7ed)