Skip to content

feat(ddi)!: every form field in the codebook, standard DDI first (#153) - #158

Merged
jstet merged 1 commit into
mainfrom
feat/153-ddi-fields
Sep 27, 2026
Merged

jstet merged 1 commit into
mainfrom
feat/153-ddi-fields

Conversation

@jstet

@jstet jstet commented Sep 27, 2026

Copy link
Copy Markdown
Member

Closes #153. Part 3 of #155, after #151 (logic) and #152 (structure).

Breaking for DDI readers: the question hint moves from preQTxt to postQTxt (the layout agreed with qwacback on #153, tracked in qwacback#37).

Standard DDI wherever one fits

Field DDI
hint qstn/postQTxt, one per xml:lang. Grid members and select_multiple options now keep theirs.
note row before a question / grid or select_multiple shared text qstn/preQTxt only; no longer joined with the hint
guidance_hint qstn/ivuInstr, now also on select_multiple options
date / time varFormat/@category="date" / "time"
integer var/@dcml="0"
range start / end valrng/range/@min / @max (registry defaults when not authored)
order qstn/@seqNo, the position among the data questions (a select_multiple's options share it)
what relevant depends on qstn/backward/@qstn, the IDs of the referenced var or varGrp

cdl: notes only where DDI 2.5 has no place

cdl:default, cdl:appearance, cdl:parameters (only what no element holds, e.g. step=5, randomize=true), a group's cdl:hint (per language), cdl:exclusive (codes, on the select_multiple's varGrp), and stdyDscr/notes type="cdl:setting" subject="style".

Guard

  • registry/conventions/ddiFields.jsonld maps every field of src/instrument/types.ts to one of three things: a standard DDI element, a cdl: note, or a documented loss.
  • tests/ts/unit/ddi/fields.test.ts fails when a field has no entry, or when the convention names a field that doesn't exist.
  • Documented losses: calculation and other unlifted columns, a choice list's name, the or_other shorthand as such, and GroupItem.closed.

LimeSurvey: integer vs decimal

  • xlsform2lstsv now writes LimeSurvey's num_value_int_only=1 for integer, and an N question with it reads back as integer.
  • This fixes lstsv2xlsform's known loss 1, which is updated in its README.
  • The TSV fixtures gain the column.

Checks

  • vitest: 1254 passed, including the new fields.test.ts.
  • pytest validation and codegen: 127 passed, 3 xfailed.
    • The XSD and Schematron checks pass on every snapshot with the new elements and attributes.
    • The known-invalid fixtures fail with the same errors as before.
    • The Schematron mutators now match <qstn responseDomainType="…" without the closing >, since seqNo follows it.
  • The schematron-worker tests pass (gradle).
  • npm run validate and the drift check are clean.

🤖 Generated with Claude Code

convention:ddiFields maps every Instrument field to a standard DDI 2.5
element or attribute, a typed `cdl:` note where DDI has none, or a
documented loss; a unit test fails when a field has none of these.

Standard DDI:
- the hint is `qstn/postQTxt` (was merged into `preQTxt`); `preQTxt` is
  only a note row before the question or a grid's / select_multiple's
  shared text. Grid members and select_multiple options now keep their
  hints, so `hint-dropped` is LimeSurvey-only.
- `varFormat/@category` date / time; `var/@dcml="0"` for integer;
  `valrng/range` for a range's start/end;
- `qstn/@seqNo` (position among the data questions) and `qstn/backward`
  (the var / varGrp IDs its relevant refers to).

Typed notes: `cdl:default`, `cdl:appearance`, `cdl:parameters` (what no
element holds), a group's `cdl:hint` per language, `cdl:exclusive` on a
select_multiple's varGrp, `stdyDscr/notes type="cdl:setting"` for style.

xlsform2lstsv writes `num_value_int_only=1` for an integer, and a
LimeSurvey N with it reads back as integer, so integer survives both ways.

BREAKING CHANGE: the question hint moves from `preQTxt` to `postQTxt`;
readers taking the hint from `preQTxt` must read `postQTxt`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jstet
jstet merged commit 09c5a84 into main Sep 27, 2026
4 checks passed
@jstet
jstet deleted the feat/153-ddi-fields branch September 27, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DDI round trips: every form field in standard DDI where possible, cdl: notes only for the rest

1 participant