Edits to a '• 1. …' bullet skip rawText/sections silently: normalizeBulletText strips only one marker
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 66/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
- Domain
- backend, testing-qa
Research direction
Start in src/lib/score/group-bullets.ts and score.ts, tracing normalizeBulletText, bulletId, bulletLineMatcher, and applyBulletTextOverrides through modern and legacy keys. Add regression coverage for glyph-plus-numbered bullets across rawText, sections, description, and removedBullets, then run npm run verify; done means edits and removals stay consistent and stored ids still resolve.
Written by the indexing model from the issue text.
Description
Problem
A bullet whose line has a glyph marker followed by a numbered marker, for example • 1. Led team of five engineers, can be edited but the edit never reaches the exported text. Nothing reports the miss.
The cause is that normalizeBulletText (src/lib/score/group-bullets.ts) is not idempotent. LEADING_MARKER_RE strips exactly one leading marker:
| input | normalizeBulletText(x) |
applied twice |
|---|---|---|
• 1. Led team |
1. led team |
led team |
- - foo |
- foo |
foo |
The edit fold normalises the same text twice on one side and once on the other, and the two results disagree:
score.ts(~L823, bullet extraction) strips the first marker (BULLET_MARKER_RE, falling back toNUMBERED_BULLET_RE). The observation text is therefore1. Led team of five engineers.bulletId(text, 0)normalises that.LEADING_MARKER_REstrips the1., which gives the id0|led team of five engineers.applyBulletTextOverrideshands the id's text tobulletLineMatcher, which normalises it again, givingled team of five engineers.- The rawText/sections line
• 1. Led team of five engineersnormalises once to1. led team of five engineers. There is no match.
Repro (verified on origin/main @ ba1d5f8)
applyOverrides with a base whose experience line is • 1. Led team of five engineers, observation text 1. Led team of five engineers, and bulletOverrides: { [bulletId(obsText, 0)]: "Led a team of eight" }:
rawText "• 1. Led team of five engineers" ← edit did NOT land
description "Led a team of eight" ← landed here only
unresolved [] ← and nothing reports the miss
A legacy numeric key ("0") resolving through byIndex hits the same mismatch.
Why it matters
- The Download PDF and anything else that reads
rawText/sections keeps the old bullet while the on-screen role shows the edit. That is the round-trip divergence the edit seam is meant to prevent. unresolved(#769) reports[]because the description match counts as a match, so the #769 channel can't surface it either.- Numbered-inside-glyph bullets come from some template exports, so this happens on real résumés.
Proposed fix
Either:
- Make
LEADING_MARKER_REstrip repeated markers (^(?:[\s ]*(?:[-*•●–▪◦‣▶►·�]|\d+[.)]) *)+), which makesnormalizeBulletTextidempotent. Checkscore.ts's extraction andbulletIdstability for existing stored ids, since a changed normalisation re-keys any stored id whose text carried a second marker. A migration note or dual-match may be needed. - Or don't re-normalise an already-normalised id text in the matcher, and compare
normalizeBulletText(line)against the id text directly, with the legacy branch normalised once. This fixes the mismatch without re-keying, but leaves the function non-idempotent.
Acceptance criteria
- A test with a
• 1. …line (glyph + numbered marker) editsrawText, sections and description through both a modern id key and a legacy numeric key - The same case on the
removedBulletschannel removes the line from all three containers - If option 1:
normalizeBulletText(normalizeBulletText(x)) === normalizeBulletText(x)is pinned by a test, and stored ids from before the change still resolve -
npm run verifygreen
Provenance: found reviewing PR #998, whose resolveOverrideOriginal docblock asserts normalizeBulletText is idempotent.
- Dominant language
- TypeScript
- Stars
- 11
- Forks
- 4
- Avg merge
- 18h 56m
- Merged PRs (30d)
- 92
Getting set up
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from offlinecv/OfflineCV
-
documentation
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Maintainers usually reply within 1 day
-
documentation
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Maintainers usually reply within 1 day
-
bug gaal ready-for-agent
Difficulty 4/5 3-5 days Newbie friendliness 58/100
Maintainers usually reply within 1 day
-
bug gaal refactor
Difficulty 4/5 3-5 days Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
[epic] Fix It guidance: advice that is right for the résumé in front of the userPossibly taken @Samhit21 claimed this today. Openimprovement ready-for-agent ux:score-clarity
offlinecv/OfflineCV#1086 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
All issues in offlinecv/OfflineCV
Similar issues
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
inu-appcenter/memorIN-frontend#106 ·
Maintainers usually reply within 1 day
-
kind/bug
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 7 days
-
[Bug] @deck.gl/arcgis dist import resolves to unpublished @deck.gl/core source path (9.3.11, 9.4.0)Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
CSCfi/sd-search-ui#145 ·
Maintainers usually reply within 1 day
-
Add: Cbeebies pl SDOpencheck:passed streams:add
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day