{"record":{"id":"5343dc7aa788b462","repo":"santifer/career-ops","slug":"sync-check-active-interviews-md-row-for-m-comp","errorCode":null,"errorMessage":"Sync check: active-interviews.md row for \"${m.company}\" — \"${m.role}\" could not be matched to a tracker row (${m.note})","messagePattern":"Sync check: active-interviews\\.md row for \"(.+?)\" — \"(.+?)\" could not be matched to a tracker row \\((.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"verify-pipeline.mjs","lineNumber":471,"sourceCode":"  // reading the exit status (CI, a cron wrapper, a pre-push hook) that is indistinguishable from\n  // the invariant holding. We do not know whether the tracker is in sync; we know we failed to\n  // look. The honest report is failure.\n  error(`Sync check could not run — the tracker was NOT verified: ${err.message}`);\n}\n\nif (syncResult) {\n  const tier1Mismatches = syncResult.mismatches.filter(m => m.resolution === 'auto-tier1');\n  const tier2Mismatches = syncResult.mismatches.filter(m => m.resolution === 'needs-review-tier2');\n  const unmatchedRows = syncResult.mismatches.filter(m => m.resolution === 'unmatched');\n\n  for (const m of tier1Mismatches) {\n    warn(`Sync drift (auto-resolvable): ${m.company} — ${m.role}: applications.md=\"${m.applicationsStatus}\" vs active-interviews.md=\"${m.activeInterviewsStatus}\" -> suggest \"${m.suggestedStatus}\" in ${m.staleIn} (run node tracker-sync-check.mjs for details)`);\n  }\n  for (const m of tier2Mismatches) {\n    warn(`Sync drift (needs human review): ${m.company} — ${m.role}: applications.md=\"${m.applicationsStatus}\" (${m.applicationsLastModified || 'no blame info'}) vs active-interviews.md=\"${m.activeInterviewsStatus}\" (${m.activeInterviewsLastModified || 'no blame info'})`);\n  }\n  for (const m of unmatchedRows) {\n    warn(`Sync check: active-interviews.md row for \"${m.company}\" — \"${m.role}\" could not be matched to a tracker row (${m.note})`);\n  }\n  if (tier1Mismatches.length === 0 && tier2Mismatches.length === 0 && unmatchedRows.length === 0) {\n    ok(syncResult.summary.total > 0\n      ? 'applications.md and active-interviews.md are in sync'\n      : 'No active-interviews.md rows to sync-check');\n  }\n}\n\n// --- Check 14: data/follow-ups.md table schema (#2971) ---\n// stats.mjs (computeFollowupStats) and followup-cadence.mjs both read this table\n// positionally, in the shape modes/followup.md documents, and both skip any row\n// whose num/appNum cells don't parse as integers. A table written with a\n// different column order therefore reports as ZERO follow-ups in both tools,\n// silently — indistinguishable from a file where nothing has been logged yet.\n// Follow-up compliance is exactly the number a user consults to decide whether\n// their follow-ups are working, so a silent zero is actively misleading. This is\n// the only place that difference is visible.\n//","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/santifer/career-ops/blob/e7abd431fce9348a95261acac9e0c14779c35df8/verify-pipeline.mjs#L453-L489","documentation":"verify-pipeline.mjs reports an unmatched row: an entry in data/active-interviews.md could not be joined to any applications.md tracker row, either by an explicit `#N in tracker` Notes reference or by fuzzy Company+Role matching. The check cannot verify its status, so it warns with the matcher's note explaining why.","triggerScenarios":"Running `node verify-pipeline.mjs` when an active-interviews.md row lacks a `#N in tracker` note, or its company/role text differs too much from the tracker row (renamed company, reworded role title, typo).","commonSituations":"Logging an interview for an application never tracked; changing the role title in one file only; company name spelled differently (e.g. 'acme.io' vs 'Acme GmbH').","solutions":["Add a `#N in tracker` reference to the row's Notes in active-interviews.md pointing at the correct tracker row number","If no tracker row exists, create one (career-ops add / merge-tracker TSV) and link it","Align the company/role spelling between the two files","Re-run tracker-sync-check.mjs to confirm the row now matches"],"exampleFix":"// before (active-interviews.md Notes)\nNotes: second round went well\n// after\nNotes: second round went well (#42 in tracker)","handlingStrategy":"validation","validationCode":"// every active-interviews row must reference a tracker row\nif (!/\\#\\d+ in tracker/.test(row.notes)) console.warn(`unmatched: ${row.company} — ${row.role}`);","typeGuard":"const hasTrackerRef = (row) => /#\\d+ in tracker/.test(row.notes || '');","tryCatchPattern":null,"preventionTips":["Always add `#N in tracker` to active-interviews.md rows","Create the tracker row before logging interview rounds","Keep company/role strings identical across both files","Run tracker-sync-check.mjs after adding interview entries"],"tags":["sync-drift","tracker","data-linking"],"backgroundTag":"record-not-found","analyzedSha":"e7abd431fce9348a95261acac9e0c14779c35df8","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}