feat: add preferences.anonymous for blind-review mode#122
Conversation
Closes #55. New boolean preference (default false). When true: - Header drops basics.name, basics.image, and the contact bar entirely. Only basics.label (e.g. "Senior Software Engineer") survives — a role title is the only header field that conveys candidate fit without identity. Per-channel opt-out for contact info already exists via linkContactInfo, so anonymous mode suppresses the bar wholesale rather than re-implementing per-channel gating. - PDF metadata title and author collapse to the placeholder "Candidate" so file properties can't leak the name through an OS file-info panel or a search index. Description (basics.summary) and keywords (skills[].keywords) stay populated — neither is identity-bearing in the same way and the issue spec only called out title/author. - Validation still runs in anonymous mode: a malformed basics.image or linkContactInfo dict still panics, so flipping the toggle later doesn't surface latent bugs. The contact-bar entry build (~75 lines) was extracted from _header into a module-level _build_contact_entries helper. Without that extraction the anonymity guard would be a pure-indentation wrap of the existing block, drowning the actual logic in diff noise. Fixture (tests/anonymous.typ, 3 pages): 1. anonymous off, full basics — regression guard against perturbations to the canonical render. 2. anonymous on, no label — header collapses cleanly (no orphan spacing). 3. anonymous on, full basics — canonical blind-review render. Rendered last so the document's set document(...) wins and pdfinfo on the tracked PDF reports title/author = "Candidate".
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds a ChangesAnonymous / blind-review mode
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Closes #55. Supersedes #68 (rewritten from scratch on top of the post-#68 refactorings:
lib.typsplit intointernal/, labels moved tointernal/labels-en.toml,example_full.typdemo).Summary
New
preferences.anonymous: bool(defaultfalse). One toggle, same data dict, same compile command — no need to fork or maintain a stripped copy ofbasics.When
true:basics.name,basics.image, and the contact bar entirely. Onlybasics.label(e.g."Senior Software Engineer") survives — a role title is the only header field that conveys candidate fit without identity. Per-channel opt-out for contact info already exists vialinkContactInfo, so anonymous mode suppresses the bar wholesale rather than re-implementing per-channel gating.titleandauthorcollapse to the placeholder"Candidate"so file properties can't leak the name through an OS file-info panel or a search index.description(frombasics.summary) andkeywords(fromskills[].keywords) stay populated — neither is identity-bearing in the same way and the issue spec only called out title/author.basics.imageorlinkContactInfodict still panics underanonymous: true, so flipping the toggle later doesn't surface latent bugs.Implementation notes
The contact-bar entry build (~75 lines) was extracted from
_headerinto a module-level_build_contact_entrieshelper. Without that extraction the anonymity guard would be a pure-indentation wrap of the existing block, drowning the actual logic in diff noise. Net effect:_headerkeeps a simple two-lineif not anonymous { ... contact bar ... }, and the entry-collection logic gets a clean home.The
has-imagelogic now readslet has-image = image-present and not anonymous— the validation branch (let image-present = ...) runs unconditionally so a badbasics.imagevalue still panics, but the rendering branch is gated on the anonymity flag.Fixture
tests/anonymous.typ(3 pages):anonymous: false, full basics — regression guard against perturbations to the canonical render.anonymous: true, no label — header collapses cleanly (no orphan vertical space between the suppressed name and the section grid).anonymous: true, full basics — canonical blind-review render. Rendered last so the document'sset document(...)wins andpdfinfo examples/tests/anonymous.pdfreportsTitle: CandidateandAuthor: Candidate, confirming identity doesn't leak through file properties either.Test plan
make test— all 38 fixtures + 4 examples compilepdfinfo examples/tests/anonymous.pdfreportsTitle: CandidateandAuthor: CandidateSummary by CodeRabbit