wizard: catch and repair Sonstiges follow-ups without relevant (#47 follow-up) - #51
Merged
Merged
Conversation
…follow-up)
A user imported a generated XLSForm into Kobo and found the conditional
logic didn't work. Cause: every `relevant` column was empty. The model
wrote follow-up text questions (Sonstiges fields, yes/no follow-ups)
but never emitted the `relevant` expression that hides them from
respondents who didn't pick the trigger choice. The validator can't
catch this — it doesn't parse `relevant` — so the file passed and
shipped with no skip-logic.
Three layers, complementary:
**A. Prompt.** Replace 'Sonstiges + a follow-up text question with
`relevant` logic instead of `or_other`' with a hard rule: the
follow-up is **required**, name it `<parent>_sonstiges` / `<parent>_other`,
and write the right expression (`selected(${parent}, '<code>')` for
select_multiple parents, `${parent} = '<code>'` for select_one /
yes-no parents). Same rule covers yes/no follow-ups.
**B. Quality check.** New `looksLikeFollowUp` heuristic in
`qualityFeedback`: a text question whose name ends in
`_sonstiges` / `_sonst` / `_other` *or* whose label starts with
'Falls Sonstiges' / 'If other', with no `relevant`, is a broken
follow-up. The gap goes into the repair loop; the repair agent fills
in the expression. The validator can't see this; the wizard-specific
check belongs in the wizard.
**C. Regression test.** End-to-end: model emits a broken follow-up,
assert the lead agent runs the repair loop and the shipped survey has
the right `relevant`. Plus unit tests for the heuristic
(name-suffix, German label prefix, English label prefix, no match,
select_one ignored, already-has-relevant). Plus a new e2e fixture
`missing-relevant-on-follow-up` documenting the failure mode in
snapshots so future work can see what the validator currently misses.
The structural 'dangling references and bad literals' check is filed
upstream as CorrelAid/formtransform#73 — that's the long-term answer
for non-formulaid users, and lands as a follow-up in formulaid once
shipped.
Verified: `npm run test:unit` (100 pass, +9), `npm run test:e2e` (49
pass, +4), `npm run check`, `npm run lint`.
This was referenced Sep 25, 2026
Closed
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.
A user imported a generated XLSForm into Kobo and found the conditional logic didn't work. Cause: every
relevantcolumn was empty. The model wrote follow-up text questions (Sonstiges fields, yes/no follow-ups) but never emitted therelevantexpression that hides them from respondents who didn't pick the trigger choice. The validator can't catch this — it doesn't parserelevant— so the file passed and shipped with no skip-logic.Three layers, complementary:
A. Prompt. Replace "Sonstiges + a follow-up text question with
relevantlogic instead ofor_other" with a hard rule: the follow-up is required, name it<parent>_sonstiges/<parent>_other, and write the right expression (selected(${parent}, '<code>')for select_multiple parents,${parent} = '<code>'for select_one / yes-no parents). Same rule covers yes/no follow-ups.B. Quality check. New
looksLikeFollowUpheuristic inqualityFeedback: a text question whose name ends in_sonstiges/_sonst/_otheror whose label starts with "Falls Sonstiges" / "If other", with norelevant, is a broken follow-up. The gap goes into the repair loop; the repair agent fills in the expression.C. Regression test. End-to-end: model emits a broken follow-up, assert the lead agent runs the repair loop and the shipped survey has the right
relevant. Plus unit tests for the heuristic (name-suffix, German label prefix, English label prefix, no match, select_one ignored, already-has-relevant). Plus a new e2e fixturemissing-relevant-on-follow-updocumenting the failure mode in snapshots so future work can see what the validator currently misses.Filed separately. The structural "dangling references and bad literals" check is filed upstream as CorrelAid/formtransform#73 — that's the long-term answer for non-formulaid users, and lands as a follow-up in formulaid once shipped.
Verified:
npm run test:unit(100 pass, +9),npm run test:e2e(49 pass, +4),npm run check,npm run lint.Closes #47 follow-up.