wizard: drop generated questions whose name collides with a demographic (#47) - #49
Merged
Merged
Conversation
…ic (#47) The model is told `demographicsAddedSeparately: 'age, ...'` but still occasionally writes a birth-date / age / sex question and names it the same as a demographic. assembleSurvey then appends the qwac copy, sanitizeSurvey renames the duplicate (e.g. 'age' -> 'age2'), and the user ends up with two 'Wann sind Sie geboren?' rows under the same name family. Filter generated questions against the demographic name set inside `evaluate()` so both the first generation and the repair loop go through it. The qwac demographic is the canonical version and stays appended by assembleSurvey; the generated duplicate is dropped before the survey is built. New helper `dedupAgainstDemographics` exported for testing; new tests in lead.test.ts cover the end-to-end path (model returns a question named 'age' alongside the demographic) and the unit cases for the helper.
jstet
force-pushed
the
issue-47-dedup-demographics
branch
from
September 25, 2026 12:54
8e633eb to
33b00ef
Compare
jstet
added a commit
that referenced
this pull request
Sep 25, 2026
… (#50) Defensive follow-up to #49: the dedup strips generated questions that land on a demographic's name, but the prompt only told the model to avoid the topic. Add an explicit 'don't reuse the names either' clause with the concrete failure mode (sanitize would leave 'age' + 'age2' both with the German birth-date label) and a couple of rename hints ('birthyear', 'age_group', 'years_active'). The dedup stays as the safety net — the prompt nudges, the code guarantees.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #48: the survey-view fix moved the divider into the right place, but the underlying duplicate was still in the workbook.
Why duplicates happened. The model is told
demographicsAddedSeparately: 'age, ...'but still occasionally writes a birth-date question and names itage(the natural word).assembleSurveythen appends the qwacagealongside it;sanitizeSurveydedupes by variable name, turning the duplicate intoage2— but the labels stay identical, so the user sees two "Wann sind Sie geboren?" rows under the same divider family.Fix. Filter generated questions against the demographic name set inside
evaluate(), so the first generation and the repair loop both go through it. The qwac demographic is the canonical version and stays appended byassembleSurvey; the generated duplicate is dropped before the survey is built. Cheap Set lookup; only kicks in when the model misbehaves.dedupAgainstDemographicsexported fromlead.tsfor testing.lead.test.ts: end-to-end (model returns a question namedagealongside the demographic — exactly the reported case), plus three unit cases for the helper.The follow-up commit on this branch strengthens the prompt so the model is less likely to do this in the first place (separate PR).
Verified:
npm run test:unit(90 pass, +3),npm run test:e2e(45 pass),npm run check,npm run lint.Closes #47.