As a clinical trial statistician or programmer, answer three short questions in Your review: the task, the inputs and outputs, and the AI-assisted review. Agreeing with all three approves this benchmark; disagreeing with any needs a comment. Propose a fix with the Edit button on any source file, or add it to your comments.
We suggest spending no more than 5 minutes on a review. The other tabs beside Your review are background for assessment, not under review.
Summary
README.mdPublic entries: Python and R. Passing coverage requires an installed inventory.
Goal: map a pre-specified medical history checklist into MH and carry any number of volunteered free-text conditions alongside it.
Input: the ODM extract has one item record for each checklist condition asked, with a blank value when it was not answered. An item-definition table gives each checklist item its reported term and form order. Each volunteered condition has its own repeated free-text record. Repeat numbers can be reused at another visit.
Variables:
MHTERMis the checklist condition from the item-definition table, or the volunteered text exactly as reported. A checklist item the table does not define stops the run.MHCATisDISEASE-SPECIFIC HISTORYfor checklist records andGENERAL HISTORYfor volunteered records.MHPRESPisYfor checklist records and blank for volunteered records.MHOCCURisYorNfor an answered checklist condition and blank otherwise.MHSTATisNOT DONEfor an unanswered checklist condition and blank otherwise.MHSEQorders checklist conditions as shown on the form, then volunteered conditions by visit and form repeat.
Note: an unanswered checklist item still has an ODM record. A question entirely absent from the extract is not assumed to have been asked. Each volunteered condition is its own MH record, even when its repeat number is reused at another visit.
Inputs
Under review2 source filesinput/mh_items.csv
Edit3 rows| ItemOID | MHTERM | SORTORD |
|---|---|---|
| IT.MH.DIABETES | DIABETES MELLITUS | 1 |
| IT.MH.HYPERTENSION | HYPERTENSION | 2 |
| IT.MH.ASTHMA | ASTHMA | 3 |
input/odm.csv
Edit10 rows| StudyOID | MetaDataVersionOID | SubjectKey | StudyEventOID | StudyEventRepeatKey | ItemGroupOID | ItemGroupRepeatKey | ItemOID | Value |
|---|---|---|---|---|---|---|---|---|
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.DIABETES | Y |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.HYPERTENSION | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.ASTHMA | — |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Seasonal allergies |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.DIABETES | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.HYPERTENSION | Y |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.ASTHMA | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.FREETEXT | 2 | IT.MH.MHTERM | Migraine |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | BASELINE | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Back pain |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Appendectomy |
Expected output
Under review10 expected rowsexpected/mh.csv
Edit10 rows| DOMAIN | STUDYID | USUBJID | MHSEQ | MHTERM | MHCAT | MHPRESP | MHOCCUR | MHSTAT |
|---|---|---|---|---|---|---|---|---|
| MH | YAMAA-01 | 1 | DIABETES MELLITUS | DISEASE-SPECIFIC HISTORY | Y | Y | — | |
| MH | YAMAA-01 | 2 | HYPERTENSION | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 3 | ASTHMA | DISEASE-SPECIFIC HISTORY | Y | — | NOT DONE | |
| MH | YAMAA-01 | 4 | Seasonal allergies | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 5 | Migraine | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 6 | Back pain | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 1 | DIABETES MELLITUS | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 2 | HYPERTENSION | DISEASE-SPECIFIC HISTORY | Y | Y | — | |
| MH | YAMAA-01 | 3 | ASTHMA | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 4 | Appendectomy | GENERAL HISTORY | — | — | — |
Human review and assessment
| Variable Name | Variable Label | Type | Length | Controlled Terms or Format | Origin | Core | Conversion Definition | Variable Type | Variable Order | Comments for Define |
|---|---|---|---|---|---|---|---|---|---|---|
| DOMAIN | Domain Abbreviation | Char | Assigned | Set constant value "MH". | SDTM | 1 | ||||
| STUDYID | Study Identifier | Char | Collected | Copy value from ODM.StudyOID. | SDTM | 2 | ||||
| USUBJID | Unique Subject Identifier | Char | Collected | Copy value from ODM.SubjectKey. | SDTM | 3 | ||||
| MHTERM | Reported Term for the Medical History | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 4 | ||||
| MHCAT | Category for Medical History | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 5 | ||||
| MHPRESP | Pre-Specified Medical History Indicator | Char | Y | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 6 | |||
| MHOCCUR | Medical History Occurrence | Char | Y, N | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 7 | |||
| MHSTAT | Completion Status | Char | NOT DONE | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 8 | |||
| MHSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by SORTORD then EVENTORD then EVENTREPEAT then REPEATKEY. | SDTM | 9 |
| Template | Include when | MHTERM | MHCAT | MHPRESP | MHOCCUR | MHSTAT | SORTORD | EVENTORD |
|---|---|---|---|---|---|---|---|---|
| checklist | ODM.StudyEventOID = 'SCREENING' AND ODM.ItemGroupOID = 'IG.MH.CHECKLIST' | If ODM.ItemGroupOID = 'IG.MH.CHECKLIST' then "MH_MAP.MHTERM"; otherwise "None" | Constant "DISEASE-SPECIFIC HISTORY" | Constant "Y" | If ODM.Value = 'Y' then "Y"; If ODM.Value = 'N' then "N"; otherwise "None" | If ODM.Value IS NULL then "NOT DONE"; otherwise "None" | If ODM.ItemGroupOID = 'IG.MH.CHECKLIST' then "MH_MAP.SORTORD"; otherwise "None" | If ODM.StudyEventOID IN ('SCREENING', 'BASELINE') then recode ODM.StudyEventOID: "SCREENING" → "1", "BASELINE" → "2"; missing values stay missing; unlisted values are errors; otherwise "99" |
| volunteered | ODM.ItemGroupOID = 'IG.MH.FREETEXT' AND ODM.ItemOID = 'IT.MH.MHTERM' AND ODM.Value IS NOT NULL | Copy ODM.Value | Constant "GENERAL HISTORY" | Constant "None" | Constant "None" | Constant "None" | Constant "4" | If ODM.ItemGroupOID = 'IG.MH.FREETEXT' AND ODM.ItemOID = 'IT.MH.MHTERM' AND ODM.Value IS NOT NULL then recode ODM.StudyEventOID: "SCREENING" → "1", "BASELINE" → "2"; missing values stay missing; unlisted values are errors; otherwise "99" |
| Variable | Permitted values |
|---|---|
| MHPRESP | Y |
| MHOCCUR | Y, N |
| MHSTAT | NOT DONE |
| Version | Date | Author | Description | Reviewer | Sign-off |
|---|---|---|---|---|---|
| 1.7 | 2026-10-20 | yamaa docs build | Read a specification in the 1.0 surface as its 0.5 counterpart; state that missing values stay missing where a mapping declares no missing handler, and leave out a declared missing answer that restates a handler's default | ||
| 1.6 | 2026-10-17 | yamaa docs build | Describe collected date parts written as ISO 8601 date text and times of day counted in seconds since midnight | ||
| 1.5 | 2026-10-17 | yamaa docs build | Name collected precision in words instead of letter codes; state imputation fallbacks, minimum source precision, bounds ignored outside the collected period, and invalid text with no handler as an error; describe date and datetime shifts, imputation flag codes, and partial text giving no date part | ||
| 1.4 | 2026-10-15 | yamaa docs build | State datetime precision codes through the hour and minute, and complete only the time parts a collected datetime lacks | ||
| 1.3 | 2026-09-29 | yamaa docs build | Show study codelist names, external dictionaries, and ISO 8601 formats in variable rows; list the document's codelist values and metadata | ||
| 1.2 | 2026-09-29 | yamaa docs build | Classify ADaM copies from a declared input as Predecessor and recodes as Derived, and SDTM recodes of locally derived columns as Derived | ||
| 1.1 | 2026-09-29 | yamaa docs build | Resolve lookups into the donor record they select, and give every derivation shape a plain-language rule instead of its raw YAML | ||
| 1.0 | yamaa docs build | Initial generation from spec.yaml |
prompts/sdtm-mh-prespecified-conditions/full.md
Edit26 linesFollowing CDISC SDTM standards, use the provided MH_ITEMS and ODM datasets to create an MH dataset with one record per condition asked about on the checklist or volunteered in free text.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
DOMAIN is "MH". STUDYID is the ODM study OID and USUBJID is the ODM subject key, each as given. Each checklist condition asked of a subject gives one record, answered or not, and a checklist condition that does not appear for the subject gives no record. MHTERM is the condition the item-definition table gives for a checklist item. For a volunteered condition, MHTERM is the volunteered text exactly as reported. MHCAT is "DISEASE-SPECIFIC HISTORY" for a checklist record and "GENERAL HISTORY" for a volunteered record. MHPRESP is "Y" for a checklist record and has no value for a volunteered record. MHOCCUR is "Y" or "N" for an answered checklist condition, as answered, and has no value otherwise. MHSTAT is "NOT DONE" when a checklist condition was not answered and has no value otherwise. Each volunteered condition is its own record, even when its form repeat number is used again at another visit. MHSEQ numbers each subject's records from 1: the checklist conditions first, in the order they are shown on the form, then the volunteered conditions by visit, screening before baseline, and then by form repeat number.
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
prompts/sdtm-mh-prespecified-conditions/conventions.md
Edit13 linesFollowing CDISC SDTM standards, use the provided MH_ITEMS and ODM datasets to create an MH dataset with one record per condition asked about on the checklist or volunteered in free text.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
DOMAIN is "MH". MHCAT is "DISEASE-SPECIFIC HISTORY" or "GENERAL HISTORY". MHPRESP is "Y" or has no value. MHOCCUR is "Y" or "N", or has no value. MHSTAT is "NOT DONE" or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
prompts/sdtm-mh-prespecified-conditions/brief.md
Edit9 linesFollowing CDISC SDTM standards, use the provided MH_ITEMS and ODM datasets to create an MH dataset with one record per condition asked about on the checklist or volunteered in free text.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/sdtm-mh-prespecified-conditions/result.R
Edit76 lines# Reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions (R track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1.library(dplyr, warn.conflicts = FALSE)library(readr)library(tidyr)items <- read_csv( "/app/input/mh_items.csv", col_types = cols(SORTORD = col_integer(), .default = col_character()))odm <- read_csv( "/app/input/odm.csv", col_types = cols(.default = col_character()))checklist_oids <- intersect(items$ItemOID, unique(odm$ItemOID))checklist <- odm |> filter(ItemOID %in% checklist_oids) |> group_by(StudyOID, SubjectKey, ItemOID) |> slice_tail(n = 1) |> ungroup() |> left_join(items |> select(ItemOID, MHTERM, SORTORD), by = "ItemOID") |> mutate( answered = Value %in% c("Y", "N"), MHTERM = MHTERM, MHCAT = "DISEASE-SPECIFIC HISTORY", MHPRESP = "Y", MHOCCUR = if_else(answered, Value, NA_character_), MHSTAT = if_else(answered, NA_character_, "NOT DONE"), visit_rank = 0L, repeat_no = 0L ) |> select( STUDYID = StudyOID, USUBJID = SubjectKey, ItemOID, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT, SORTORD, visit_rank, repeat_no )volunteered <- odm |> filter(!ItemOID %in% checklist_oids, !is.na(Value) & Value != "") |> mutate( MHTERM = Value, MHCAT = "GENERAL HISTORY", MHPRESP = NA_character_, MHOCCUR = NA_character_, MHSTAT = NA_character_, SORTORD = NA_integer_, visit_rank = case_when( StudyEventOID == "SCREENING" ~ 0L, StudyEventOID == "BASELINE" ~ 1L, TRUE ~ 99L ), repeat_no = suppressWarnings(as.integer(ItemGroupRepeatKey)) ) |> select( STUDYID = StudyOID, USUBJID = SubjectKey, ItemOID, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT, SORTORD, visit_rank, repeat_no )mh <- bind_rows(checklist, volunteered) |> arrange(USUBJID, is.na(SORTORD), SORTORD, visit_rank, repeat_no) |> group_by(USUBJID) |> mutate(MHSEQ = row_number()) |> ungroup() |> mutate(DOMAIN = "MH") |> arrange(USUBJID, MHSEQ) |> select( DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT )dir.create("/app/output", showWarnings = FALSE)write_csv(mh, "/app/output/mh.csv", na = "")solutions/sdtm-mh-prespecified-conditions/result.py
Edit114 lines# Reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions (Python track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1.from pathlib import Pathimport polars as pldef _present(value) -> bool: return value is not None and str(value) != ""items = pl.read_csv("/app/input/mh_items.csv", infer_schema=False)odm = pl.read_csv("/app/input/odm.csv", infer_schema=False)meta = {row["ItemOID"]: (row["MHTERM"], int(row["SORTORD"])) for row in items.to_dicts()}checklist_oids = {oid for oid in meta if (odm["ItemOID"] == oid).any()}visit_order = {"SCREENING": 0, "BASELINE": 1}records_by_subject: dict[tuple[str, str], dict] = {}for row in odm.to_dicts(): studyid, usubjid = str(row["StudyOID"]), str(row["SubjectKey"]) key = (studyid, usubjid) records_by_subject.setdefault(key, {"checklist": {}, "volunteered": []})for row in odm.to_dicts(): key = (str(row["StudyOID"]), str(row["SubjectKey"])) oid, value = str(row["ItemOID"]), row["Value"] if oid in checklist_oids: # Last collected answer wins when an item repeats, including blanks. records_by_subject[key]["checklist"][oid] = value if _present(value) else None elif not _present(value): continue else: # Each volunteered condition is its own record, even when its # repeat number is reused at another visit. event = str(row["StudyEventOID"]) records_by_subject[key]["volunteered"].append( { "term": str(value), "visit_rank": visit_order.get(event, 99), "repeat": int(row["ItemGroupRepeatKey"] or 1), } )rows = []for (studyid, usubjid), parts in records_by_subject.items(): ordered = sorted(parts["checklist"].items(), key=lambda kv: meta[kv[0]][1]) seq = 0 for oid, answer in ordered: seq += 1 term, _ = meta[oid] answered = answer in ("Y", "N") rows.append( { "DOMAIN": "MH", "STUDYID": studyid, "USUBJID": usubjid, "MHSEQ": str(seq), "MHTERM": term, "MHCAT": "DISEASE-SPECIFIC HISTORY", "MHPRESP": "Y", "MHOCCUR": answer if answered else None, "MHSTAT": None if answered else "NOT DONE", } ) volunteered = sorted( parts["volunteered"], key=lambda v: (v["visit_rank"], v["repeat"]) ) for entry in volunteered: seq += 1 rows.append( { "DOMAIN": "MH", "STUDYID": studyid, "USUBJID": usubjid, "MHSEQ": str(seq), "MHTERM": entry["term"], "MHCAT": "GENERAL HISTORY", "MHPRESP": None, "MHOCCUR": None, "MHSTAT": None, } )mh = ( pl.DataFrame( rows, schema={ "DOMAIN": pl.String, "STUDYID": pl.String, "USUBJID": pl.String, "MHSEQ": pl.String, "MHTERM": pl.String, "MHCAT": pl.String, "MHPRESP": pl.String, "MHOCCUR": pl.String, "MHSTAT": pl.String, }, ) .with_columns(pl.col("MHSEQ").cast(pl.Int64).alias("_seq")) .sort(["USUBJID", "_seq"]) .select( "DOMAIN", "STUDYID", "USUBJID", "MHSEQ", "MHTERM", "MHCAT", "MHPRESP", "MHOCCUR", "MHSTAT", ))Path("/app/output").mkdir(exist_ok=True)mh.write_csv("/app/output/mh.csv")solutions/sdtm-mh-prespecified-conditions/result.sas
Edit33 lines/* opensas reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data mh_items; length ItemOID MHTERM SORTORD $1024; infile "/app/input/mh_items.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input ItemOID : $char1024. MHTERM : $char1024. SORTORD : $char1024.;run;data odm; length StudyOID MetaDataVersionOID SubjectKey StudyEventOID StudyEventRepeatKey ItemGroupOID ItemGroupRepeatKey ItemOID Value $1024; infile "/app/input/odm.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input StudyOID : $char1024. MetaDataVersionOID : $char1024. SubjectKey : $char1024. StudyEventOID : $char1024. StudyEventRepeatKey : $char1024. ItemGroupOID : $char1024. ItemGroupRepeatKey : $char1024. ItemOID : $char1024. Value : $char1024.;run;data authored; set odm; ordinal=_n_; run;proc sql; create table checklist as select a.*,b.MHTERM,b.SORTORD from authored a inner join mh_items b on a.ItemOID=b.ItemOID; quit;proc sort data=checklist; by StudyOID SubjectKey ItemOID ordinal; run;data checklistlast; set checklist; by StudyOID SubjectKey ItemOID; if last.ItemOID; run;data checklistout; set checklistlast; length DOMAIN $2 STUDYID USUBJID MHCAT MHPRESP MHOCCUR MHSTAT $1024; DOMAIN='MH'; STUDYID=StudyOID; USUBJID=SubjectKey; MHCAT='DISEASE-SPECIFIC HISTORY'; MHPRESP='Y'; MHOCCUR=''; MHSTAT='NOT DONE'; if Value in ('Y','N') then do; MHOCCUR=Value; MHSTAT=''; end; SECTION=0; ORD=input(SORTORD,best32.); VISITORD=0; REP=0; run;data volunteered; set odm; where ItemOID='IT.MH.MHTERM' and not missing(Value); length DOMAIN $2 STUDYID USUBJID MHTERM MHCAT MHPRESP MHOCCUR MHSTAT $1024; DOMAIN='MH'; STUDYID=StudyOID; USUBJID=SubjectKey; MHTERM=Value; MHCAT='GENERAL HISTORY'; MHPRESP=''; MHOCCUR=''; MHSTAT=''; SECTION=1; ORD=0; VISITORD=0; if StudyEventOID='BASELINE' then VISITORD=1; REP=input(ItemGroupRepeatKey,best32.); run;data prepared; set checklistout volunteered; run;proc sort data=prepared; by STUDYID USUBJID SECTION ORD VISITORD REP; run;data result; set prepared; by STUDYID USUBJID; retain MHSEQ; if first.USUBJID then MHSEQ=0; MHSEQ+1;run;proc sql; create table final as select DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT from result;quit;proc export data=final outfile="/app/output/mh.csv" dbms=csv replace; run;
yamaa