You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Word resume template — name, phone, and skills mis-parsed (completeness 12/30)
Using a resume sample from a Microsoft Word "Office Manager" template, the phone number was visible in the extracted plain-text panel but did not appear in the score card. Deeper investigation shows the phone is one of three parsing failures on this document; overall completeness is 12/30.
Chanchal sharma sample.pdf (synthetic persona — PII-verified safe: body text, Info dict, XMP metadata, and fonts/ICC layers all checked clean)
Running the full cascade on the attached PDF yields overall 12, completeness 12/30, with name, phone, and skills all reported as missing. The text layer is clean (ASCII + one en-dash; verified at codepoint level — no ToUnicode/CMap mojibake). The failures are entirely in the Tier-1 heuristic parser, which makes three layout assumptions that Word table/text-box templates break simultaneously.
Reproduction
Open the attached PDF in ResumeLint.
Observe completeness = 12/30.
Score card shows name, phone, and skills missing (among others — see "Out of scope" below for the non-bugs).
Expected: name, phone, and skills all parsed and scored.
Root cause
Word's resume templates lay out the header name and skills section in tables/text-boxes. This produces three independent assumption-breaks in the single-pass heuristic parser:
Name (src/lib/heuristics/extract-fields.ts:173) — The real name renders as two separate single-word lines (Chanchal / Sharma). extractName rejects any candidate with words.length < 2, so both name lines are individually disqualified. The two-word tagline "Office Manager" wins the slot at confidence 0.25 (below the anonymous contact floor of 0.5), and name is reported missing.
Phone (src/lib/heuristics/phone.ts:187-200) — The phone number is (718) 555–0100 where the separator is an en-dash U+2013, not an ASCII hyphen. mightHavePhone() pre-gates on PHONE_RE whose separator class [\s.-]? excludes Unicode dashes, so PHONE_RE.test() returns false and findPhoneNumbersInText (PR feat(phone): locale-aware region derivation + fix two-column fixture phone #100, libphonenumber-js) is never invoked. findPhoneNumbersInText handles en-dashes natively — the fix is to make the pre-filter gate wide enough to let the call reach it, not to widen PHONE_RE itself.
Skills (src/lib/heuristics/extract-fields.ts:469) — The skills are in a 3-column table. SKILL_SPLIT_RE = /[,;·•|/]+|\s{2,}/ splits correctly when pdfjs assembles a column row with 2+ spaces between entries. When a row is assembled with only a single space between columns, the entire row collapses to one token ("Organization Problem-solving Management"), which counts as 1 skill — below the minimum of 5 (extract-fields.ts:512) — so skills is reported missing.
Note: the text layer is not the problem. Fonts are subsetted Georgia + Calibri with a valid ToUnicode map; the raw text the cascade sees is byte-for-byte the visible text. ToUnicode/CMap mojibake is not the cause here.
Scope — what to fix
Name: reconstruct two-word name from adjacent single-word lines. When consecutive short lines at the top of the document together form a plausible full name (two words, title-cased), treat them as a single candidate before applying the words.length < 2 guard. (src/lib/heuristics/extract-fields.ts:165-205)
Phone: expand mightHavePhone's pre-filter to recognize Unicode dashes. In phone.ts:187-200, widen the pre-gate so that en-dash (U+2013), em-dash (U+2014), and figure dash (U+2012) allow the string through to findPhoneNumbersInText. PR feat(phone): locale-aware region derivation + fix two-column fixture phone #100 already wires findPhoneNumbersInText (which handles these chars natively) — the only missing piece is that mightHavePhone gates it out before it runs. Do not widen PHONE_RE itself — the fix is the pre-filter gate, not the regex matcher.
Skills: context-detect a single-space multi-token column run and split accordingly. When inside a recognized skills section, detect a run of tokens that are separated by single spaces and together form a plausible skills list, then split it. Do not widen SKILL_SPLIT_RE to \s+ unconditionally — that causes false-positive splits in ordinary prose. (src/lib/heuristics/extract-fields.ts:469)
Explicitly out of scope
Role dates showing as missing — The template uses placeholder text January 20XX / Sep 20XX. YEAR_RE = /\b(19|20)\d{2}\b/ correctly rejects 20XX. This is a fixture artifact (template placeholder), not a product bug. Do not modify YEAR_RE to accept 20XX as a valid year.
Summary missing — The template genuinely has no Summary, Objective, or Profile section. Not a detection failure.
LinkedIn missing — No LinkedIn URL appears in the document. Not a detection failure.
Acceptance criteria
parsed.name is the real name (not "Office Manager") for the Chanchal Word PDF.
parsed.phone is (718) 555-0100 (or equivalent normalized form) for the Chanchal Word PDF.
parsed.skills contains at least the skills visible in the template columns for the Chanchal Word PDF.
Completeness score rises above the 12/30 baseline for this document (role-dates, summary, and LinkedIn remain correctly absent — no strict numeric floor beyond the current baseline).
The committed Word fixture's expected snapshot is updated to reflect the corrected parsed output.
Test fixture
Commit the attached PDF to tests/fixtures/pdfs/word/chanchal-sharma-sample.pdf. The file has been verified PII-safe across all four layers (body text via pdftotext, Info dict via pdfinfo, XMP metadata, and fonts/ICC). After implementing fixes:
npm run bake-fixtures
Review and commit the updated expected snapshot. This fixture regression-guards all three fixes simultaneously.
Word resume template — name, phone, and skills mis-parsed (completeness 12/30)
Using a resume sample from a Microsoft Word "Office Manager" template, the phone number was visible in the extracted plain-text panel but did not appear in the score card. Deeper investigation shows the phone is one of three parsing failures on this document; overall completeness is 12/30.
Chanchal sharma sample.pdf (synthetic persona — PII-verified safe: body text, Info dict, XMP metadata, and fonts/ICC layers all checked clean)
Screenshot 1 — phone present in plain-text panel
Screenshot 2 — phone absent from score card
Summary
Running the full cascade on the attached PDF yields
overall 12,completeness 12/30, with name, phone, and skills all reported as missing. The text layer is clean (ASCII + one en-dash; verified at codepoint level — no ToUnicode/CMap mojibake). The failures are entirely in the Tier-1 heuristic parser, which makes three layout assumptions that Word table/text-box templates break simultaneously.Reproduction
Expected: name, phone, and skills all parsed and scored.
Root cause
Word's resume templates lay out the header name and skills section in tables/text-boxes. This produces three independent assumption-breaks in the single-pass heuristic parser:
Name (
src/lib/heuristics/extract-fields.ts:173) — The real name renders as two separate single-word lines (Chanchal/Sharma).extractNamerejects any candidate withwords.length < 2, so both name lines are individually disqualified. The two-word tagline "Office Manager" wins the slot at confidence 0.25 (below the anonymous contact floor of 0.5), and name is reported missing.Phone (
src/lib/heuristics/phone.ts:187-200) — The phone number is(718) 555–0100where the separator is an en-dash U+2013, not an ASCII hyphen.mightHavePhone()pre-gates onPHONE_REwhose separator class[\s.-]?excludes Unicode dashes, soPHONE_RE.test()returns false andfindPhoneNumbersInText(PR feat(phone): locale-aware region derivation + fix two-column fixture phone #100,libphonenumber-js) is never invoked.findPhoneNumbersInTexthandles en-dashes natively — the fix is to make the pre-filter gate wide enough to let the call reach it, not to widenPHONE_REitself.Skills (
src/lib/heuristics/extract-fields.ts:469) — The skills are in a 3-column table.SKILL_SPLIT_RE = /[,;·•|/]+|\s{2,}/splits correctly when pdfjs assembles a column row with 2+ spaces between entries. When a row is assembled with only a single space between columns, the entire row collapses to one token ("Organization Problem-solving Management"), which counts as 1 skill — below the minimum of 5 (extract-fields.ts:512) — so skills is reported missing.Note: the text layer is not the problem. Fonts are subsetted Georgia + Calibri with a valid ToUnicode map; the raw text the cascade sees is byte-for-byte the visible text. ToUnicode/CMap mojibake is not the cause here.
Scope — what to fix
Name: reconstruct two-word name from adjacent single-word lines. When consecutive short lines at the top of the document together form a plausible full name (two words, title-cased), treat them as a single candidate before applying the
words.length < 2guard. (src/lib/heuristics/extract-fields.ts:165-205)Phone: expand
mightHavePhone's pre-filter to recognize Unicode dashes. Inphone.ts:187-200, widen the pre-gate so that en-dash (U+2013), em-dash (U+2014), and figure dash (U+2012) allow the string through tofindPhoneNumbersInText. PR feat(phone): locale-aware region derivation + fix two-column fixture phone #100 already wiresfindPhoneNumbersInText(which handles these chars natively) — the only missing piece is thatmightHavePhonegates it out before it runs. Do not widenPHONE_REitself — the fix is the pre-filter gate, not the regex matcher.Skills: context-detect a single-space multi-token column run and split accordingly. When inside a recognized skills section, detect a run of tokens that are separated by single spaces and together form a plausible skills list, then split it. Do not widen
SKILL_SPLIT_REto\s+unconditionally — that causes false-positive splits in ordinary prose. (src/lib/heuristics/extract-fields.ts:469)Explicitly out of scope
Role dates showing as missing — The template uses placeholder text
January 20XX/Sep 20XX.YEAR_RE = /\b(19|20)\d{2}\b/correctly rejects20XX. This is a fixture artifact (template placeholder), not a product bug. Do not modifyYEAR_REto accept20XXas a valid year.Summary missing — The template genuinely has no Summary, Objective, or Profile section. Not a detection failure.
LinkedIn missing — No LinkedIn URL appears in the document. Not a detection failure.
Acceptance criteria
parsed.nameis the real name (not "Office Manager") for the Chanchal Word PDF.parsed.phoneis(718) 555-0100(or equivalent normalized form) for the Chanchal Word PDF.parsed.skillscontains at least the skills visible in the template columns for the Chanchal Word PDF.Test fixture
Commit the attached PDF to
tests/fixtures/pdfs/word/chanchal-sharma-sample.pdf. The file has been verified PII-safe across all four layers (body text viapdftotext, Info dict viapdfinfo, XMP metadata, and fonts/ICC). After implementing fixes:Review and commit the updated expected snapshot. This fixture regression-guards all three fixes simultaneously.