parser: dateless anchor-line flush-right location glue not peeled (follow-up to #891)
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- typescript
- Ambito
- backend
Direzione di ricerca
Start in src/lib/heuristics/entry-blocks.ts, tracing the dateless anchor path and the existing splitOnFlushRightGap and peelFlushRightLocation logic from line-assembly.ts. Read belowHeaderCandidates and disambiguateCompanyTitle to determine where a peeled location can land for first_line projects and achievements. Add a dateless-anchor fixture and verify the flush-right location is preserved without breaking title/company disambiguation.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Decisions (2026-09-29)
- Peel only for anchors whose entry type has a
locationfield — experience and education. Projects and achievements (first_linesections whose entries carry no location) are left untouched; their anchor text stays verbatim. - Reproduce with a synthetic generated fixture. No real corpus case is confirmed, so the implementer builds a synthetic repro via a
scripts/fixtures/gen-*.mjsgenerator + bake, under the repo's synthetic-PII rules. The fixture must fail before the fix and pass after.
Problem
#891 / PR #895 fixed a tab-justified flush-right work-mode/location keyword ("Remote"/"Hybrid"/"On-site") glued onto a role's title when title and location render on the same PDF row — but only for below-anchor header lines (peelFlushRightLocation, src/lib/heuristics/entry-blocks.ts, defined ~:1320 and wired into the belowHeaderLines loop ~:1685).
A dateless anchor line — an anchor where shouldParseAnchorDate returns false (e.g. cfg.anchor === "first_line" sections, or a date_range-anchor entry with no parseable date) — takes anchorLine.text verbatim with no peel (~:1650):
const anchorTextWithoutDates = parseAnchorDate
? stripDateRange(anchorHeadText)
: anchorLine.text; // <- no peel applied here
So the same flush-right glue on the anchor line itself still merges the keyword into the title/anchor text and the location is lost the same way #891 described.
Scope note
Flagged during review of PR #895 (comment) as narrow and untested; not confirmed against a real corpus entry, hence the synthetic repro below. Deliberately left out of #895's dated/below-anchor scope.
Approach
Apply the same splitOnFlushRightGap (line-assembly.ts) geometry check to anchorLine when !parseAnchorDate, gated by the same closed isBareLocationString vocabulary as peelFlushRightLocation, and only when the section's entry type has a location field (experience, education). For projects/achievements, keep anchorLine.text verbatim.
Care needed: the anchor line feeds title/company disambiguation directly (not just a below-anchor header candidate), so the peeled trailer needs a landing spot equivalent to what belowHeaderCandidates gives disambiguateCompanyTitle today, and it must fill location only when the header itself yielded none (mirroring the existing below-anchor rule). Determine how the location-bearing gate is expressed (e.g. an explicit flag on EntryBlockConfig or derived from the section's entry type) by mirroring how the existing location fill is wired — do not special-case by section name inline.
Repro fixture (required)
- Build a synthetic PDF: a dateless anchor line in a location-bearing section (e.g. an experience/education entry) whose title and a bare work-mode/location keyword sit on one row with a flush-right gap. Model the generator on an existing sibling such as
scripts/fixtures/gen-two-line-role-header-right-location.mjsand bake it (npm run bake-fixtures). - Synthetic persona per the repo hard rule: fake name,
@example.comemail, real area code +555exchange +0100–0199subscriber. Runnpm run check:fixturesand readpdftotext <file>.pdf - | head -40. - Fail-before proof: show the fixture's assertion failing on current
main(keyword glued into the title, location empty) before applying the fix. - Add a negative/untouched case (or test) showing a projects/achievements dateless anchor with the same shape is not peeled.
Out of scope / deferred
- Peeling for projects/achievements anchors (no
locationfield) — not done. - Below-anchor peel (already shipped in #895) and the dated-anchor path.
- Any widening of the
isBareLocationStringvocabulary.
Acceptance criteria
- A synthetic dateless-anchor fixture with flush-right work-mode/location glue exists (generator under
scripts/fixtures/+ bake) and fails before the fix - After the fix, the title/anchor text is clean and the location lands in
locationfor experience/education entries - Projects/achievements anchors are unchanged (test covers it)
- The peel uses the same geometry check + closed vocabulary as
peelFlushRightLocation; no new vocabulary - Corpus baselines/gates (
npm run verify) pass; any baseline change is limited to the new fixture
- Lingua principale
- TypeScript
- Stelle
- 11
- Fork
- 4
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di offlinecv/OfflineCV
-
fix(heuristics): unit number before a Saint-named city drops "St." from the locationForse già presa @gaal-agent l’ha presa 10 giorni fa. Apertabug gaal ux:parsing
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
-
Migrate Gaal implement/review/revise to the local gaal watch; keep mechanical workflows on ActionsApertaarchitecture chore github_actions needs-human ready-for-agent
Difficoltà 5/5 Più di una settimana Idoneità per principianti 8/100
-
Parser: achievement year lost on re-import when '· YYYY' wrapped to its own lineForse già presa @gaal-agent l’ha presa 6 giorni fa. Apertabug gaal ready-for-agent ux:parsing
Difficoltà 3/5 1-2 giorni Idoneità per principianti 25/100
-
Export: auto-bolded metric bullets extract one word per line in stream-order parsers (pypdf/Drive)Forse già presa @gaal-agent l’ha presa 6 giorni fa. Apertabatch:export-standards bug gaal ready-for-agent ux:edit-export
Difficoltà 3/5 1-2 giorni Idoneità per principianti 25/100
-
bug duplicate improvement
Difficoltà 3/5 Mezza giornata Idoneità per principianti 66/100
Tutte le issue di offlinecv/OfflineCV
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
radix-ui/primitives#4228 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
SignalK/freeboard-sk#1093 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
[测试] 等待仓库加载后再记录多仓库排序基线Forse già presa @myot233 l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno