{"record":{"id":"c44701a90f76078b","repo":"santifer/career-ops","slug":"follow-ups-md-fups-unparsedlines-length-of-f","errorCode":null,"errorMessage":"follow-ups.md: ${fups.unparsedLines.length} of ${fups.dataRows} rows will be skipped by stats.mjs and followup-cadence.mjs (line${fups.unparsedLines.length === 1 ? '' : 's'} ${fups.unparsedLines.join(', ')}) — expected ${FOLLOWUPS_COLUMNS}","messagePattern":"follow-ups\\.md: (.+?) of (.+?) rows will be skipped by stats\\.mjs and followup-cadence\\.mjs \\(line(.+?) (.+?)\\) — expected (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"verify-pipeline.mjs","lineNumber":498,"sourceCode":"// Path resolution deliberately matches the two consumers (CAREER_OPS/data/...)\n// rather than APPS_FILE's directory: the check exists to predict what they will\n// do, so it has to read the same file they read.\nconst FOLLOWUPS_FILE = join(CAREER_OPS, 'data', 'follow-ups.md');\nconst FOLLOWUPS_COLUMNS = '| num | appNum | date | company | role | channel | contact | notes |';\nif (!existsSync(FOLLOWUPS_FILE)) {\n  ok('No follow-ups.md yet — nothing to schema-check');\n} else {\n  const fups = checkFollowupsSchema(readFileSync(FOLLOWUPS_FILE, 'utf-8'));\n  if (fups.pipeLines === 0) {\n    ok('follow-ups.md has no table rows yet');\n  } else if (!fups.sawSeparator) {\n    error(`follow-ups.md has table rows but no header delimiter row, so every row is skipped — expected ${FOLLOWUPS_COLUMNS} (see modes/followup.md)`);\n  } else if (fups.dataRows === 0) {\n    ok('follow-ups.md has no logged follow-ups yet');\n  } else if (fups.parsed === 0) {\n    error(`follow-ups.md: none of its ${fups.dataRows} row(s) parse, so stats.mjs and followup-cadence.mjs will both report zero follow-ups — expected column order ${FOLLOWUPS_COLUMNS} (see modes/followup.md)`);\n  } else if (fups.unparsedLines.length > 0) {\n    warn(`follow-ups.md: ${fups.unparsedLines.length} of ${fups.dataRows} rows will be skipped by stats.mjs and followup-cadence.mjs (line${fups.unparsedLines.length === 1 ? '' : 's'} ${fups.unparsedLines.join(', ')}) — expected ${FOLLOWUPS_COLUMNS}`);\n  } else {\n    ok(`follow-ups.md schema valid (${fups.parsed} logged follow-up${fups.parsed === 1 ? '' : 's'})`);\n  }\n}\n\n// --- Summary ---\nconsole.log('\\n' + '='.repeat(50));\nconsole.log(`📊 Pipeline Health: ${errors} errors, ${warnings} warnings`);\nif (errors === 0 && warnings === 0) {\n  console.log('🟢 Pipeline is clean!');\n} else if (errors === 0) {\n  console.log('🟡 Pipeline OK with warnings');\n} else {\n  console.log('🔴 Pipeline has errors — fix before proceeding');\n}\n\nprocess.exit(errors > 0 ? 1 : 0);\n","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/santifer/career-ops/blob/60398d6549a46f5266929538af21cfab94badc75/verify-pipeline.mjs#L480-L516","documentation":"Error \"follow-ups.md: ${fups.unparsedLines.length} of ${fups.dataRows} rows will be skipped by stats.mjs and followup-cadence.mjs (line${fups.unparsedLines.length === 1 ? '' : 's'} ${fups.unparsedLines.join(', ')}) — expected ${FOLLOWUPS_COLUMNS}\" thrown in santifer/career-ops.","triggerScenarios":"Thrown at verify-pipeline.mjs:498 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"60398d6549a46f5266929538af21cfab94badc75","analyzedAt":"2026-08-20T23:00:06.764Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}