{"record":{"id":"040c530e9182432e","repo":"santifer/career-ops","slug":"application-answers-section-has-skipped-length","errorCode":null,"errorMessage":"Application Answers section has ${skipped.length} unreadable ${skipped.length === 1 ? 'entry' : 'entries'}: ${skipped.join(' | ')}","messagePattern":"Application Answers section has (.+?) unreadable (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"application-answers.mjs","lineNumber":311,"sourceCode":"    afterHeading,\n    nextHeading ? afterHeading + nextHeading.index : report.length,\n  );\n\n  const dateHit = /^\\*\\*Date:\\*\\*\\s*(.*)$/m.exec(body);\n  const stateHit = /^\\*\\*State:\\*\\*\\s*(.*)$/m.exec(body);\n  const groups = sliceGroups(body);\n\n  const snapshot = {\n    date: dateHit ? dateHit[1].trim() : '',\n    state: stateHit ? stateHit[1].trim().toLowerCase() : '',\n    freeText: parseQaEntries(groups.freeText, 'question', 'answer', onSkip),\n    selections: parseCompactEntries(groups.selections, 'question', 'selection', onSkip),\n    fieldValues: parseCompactEntries(groups.fieldValues, 'question', 'answer', onSkip),\n    files: parseFileEntries(groups.files, onSkip),\n  };\n\n  if (strict && skipped.length) {\n    throw new Error(\n      `Application Answers section has ${skipped.length} unreadable ` +\n      `${skipped.length === 1 ? 'entry' : 'entries'}: ${skipped.join(' | ')}`,\n    );\n  }\n  return snapshot;\n}\n\nexport function upsertApplicationAnswersSection(reportText, snapshot = {}) {\n  const report = String(reportText ?? '').replace(/\\r\\n/g, '\\n');\n  const section = formatApplicationAnswersSection(snapshot).trimEnd();\n  const heading = /^## Application Answers\\s*$/m.exec(report);\n\n  if (!heading) {\n    return `${report.trimEnd()}\\n\\n${section}\\n`;\n  }\n\n  const start = heading.index;\n  const afterHeading = start + heading[0].length;","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/santifer/career-ops/blob/60398d6549a46f5266929538af21cfab94badc75/application-answers.mjs#L293-L329","documentation":"Emitted by Check 13 of verify-pipeline.mjs for active-interviews.md rows classified resolution 'unmatched': checkTrackerSync could not pair the row with any applications.md row. Matching relies on a '#N in tracker' Notes reference or fuzzy Company+Role; m.note states why both failed for this row, so the sync check cannot reason about its status at all.","triggerScenarios":"An active-interviews row typed by hand with no '#N in tracker' reference and company/role spelled differently from the tracker (legal name vs brand name, abbreviations, localized spellings); a row for a company that was never added to applications.md.","commonSituations":"Interview prep written up before the tracker row was merged; copy-paste from an invite email whose company naming differs from the tracker; agencies renaming the employer between application and interview stages.","solutions":["Add '#17 in tracker' (the tracker row's number) to the active-interviews row's Notes so matching becomes exact","Or align the Company/Role spelling in active-interviews.md with the applications.md row","If no tracker row exists at all, add one via a batch/tracker-additions TSV and `node merge-tracker.mjs`, then reference it","Re-run `node verify-pipeline.mjs`"],"exampleFix":"// before (data/active-interviews.md row):\n| Acme GmbH | Backend Engineer | R2 scheduled | ... |\n\n// after:\n| Acme GmbH | Backend Engineer | R2 scheduled | #17 in tracker | ... |","handlingStrategy":"validation","validationCode":"// Run when writing an active-interviews row: guarantee it can be matched back\n// to a tracker row by the exact '#N in tracker' reference.\nexport function trackerRef(num) { return `#${num} in tracker`; }\nexport function rowIsMatchable(notes, trackerNums) {\n  const m = String(notes ?? '').match(/#(\\d+) in tracker/);\n  return !!m && trackerNums.has(Number(m[1]));\n}","typeGuard":"const hasTrackerReference = (notes) => /#\\d+ in tracker/.test(String(notes ?? ''));","tryCatchPattern":null,"preventionTips":["Always write '#N in tracker' in the Notes of every active-interviews row at creation time — exact matching beats fuzzy on renamed companies","Copy company/role spelling verbatim from the applications.md row when creating interview-prep rows","Create the tracker row first (TSV + merge), then the interview row that references it","Run verify-pipeline.mjs before interview prep so unmatched rows surface while the context is fresh"],"tags":["unmatched-row","tracker-sync","active-interviews","fuzzy-matching"],"backgroundTag":"row-matching-failure","analyzedSha":"60398d6549a46f5266929538af21cfab94badc75","analyzedAt":"2026-08-20T23:00:06.764Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}