Review ask

As a clinical trial statistician or programmer, challenge anything in this benchmark: describe a problem in Comments, or propose a fix with the Edit button on any source file.

  1. Task: Would a real study need this derivation, specified this way? Does it follow CDISC SDTM: variable names, controlled terms, record structure? Flag any rule that is ambiguous or that a sponsor would handle differently.
  2. Inputs: Do they look like data collected in a real trial, and do they include the situations you would expect to meet in one?
  3. Expected output: Would independent QC programming reproduce every value from these inputs and rules?

The other tabs beside Comments are background for assessment, not under review.

Summary

Lifecycle: draftEditUnder review
What this benchmark means
README.md

Goal: build one record per identified tumor or lesion, carrying the link identifier, the identification test and result, the anatomical location, the identification method, the evaluator, and the visit: TULNKID, TUTESTCD, TUTEST, TUORRES, TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, and TUDTC.

Input: collected lesion identification with one row per lesion, carrying the collected lesion category, lesion number, location, laterality, method, evaluator, visit, and identification date, plus study, subject, and sequence (TUSEQ) identifiers.

Variables:

  • TUSEQ numbers a subject's identification records in collection order, starting at 1.
  • TULNKID is the link identifier tying the lesion to its assessments in the tumor results (TR) domain: T plus the lesion number for a target lesion, NT for a non-target lesion, NEW for a new lesion.
  • TUTESTCD is TUMIDENT and TUTEST is Tumor Identification on every record.
  • TUORRES is the lesion category as collected, standardized to TARGET, NON-TARGET, or NEW.
  • TUSTRESC repeats the standardized category.
  • TULOC is the anatomical location as collected, standardized to uppercase.
  • TULAT is the laterality as collected, standardized to LEFT or RIGHT; empty when the site recorded none.
  • TUMETHOD is the identification method as collected.
  • TUEVAL names the evaluator as collected.
  • VISITNUM is the visit number as collected.
  • TUDTC is the date of the scan or examination that identified the lesion, as collected.

Note: a lymph-node target lesion is identified like any other target lesion: it keeps a T link identifier and its category stays TARGET; its location names it as a lymph node, and the results domain measures its short axis. A new lesion is identified once, at the visit where it first appears, and earlier visits keep no record of it.

Inputs

Under review
1 source file

input/tu_raw.csv

Edit
6 rows
input/tu_raw.csv
STUDYIDUSUBJIDTUSEQLESION_CATEGORYLESION_NUMLOCATIONLATERALITYMETHODEVALUATORVISITNUMVISITTUDTC
YAMAA-011Target01LiverRightCT SCANINVESTIGATOR1SCREENING2026-01-05
YAMAA-012Target02Mediastinal lymph node—CT SCANINVESTIGATOR1SCREENING2026-01-05
YAMAA-013Non-target01LungLeftCT SCANINVESTIGATOR1SCREENING2026-01-05
YAMAA-014New01Adrenal glandRightCT SCANINVESTIGATOR4WEEK 122026-03-30
YAMAA-011Target01LiverLeftCT SCANINVESTIGATOR1SCREENING2026-01-12
YAMAA-012Non-target01Bone—CT SCANINVESTIGATOR1SCREENING2026-01-12

Expected output

Under review
6 expected rows

expected/tu.csv

Edit
6 rows
expected/tu.csv
DOMAINSTUDYIDUSUBJIDTUSEQTULNKIDTUTESTCDTUTESTTUORRESTUSTRESCTULOCTULATTUMETHODTUEVALVISITNUMVISITTUDTC
TUYAMAA-011T01TUMIDENTTumor IdentificationTARGETTARGETLIVERRIGHTCT SCANINVESTIGATOR1SCREENING2026-01-05
TUYAMAA-012T02TUMIDENTTumor IdentificationTARGETTARGETMEDIASTINAL LYMPH NODE—CT SCANINVESTIGATOR1SCREENING2026-01-05
TUYAMAA-013NT01TUMIDENTTumor IdentificationNON-TARGETNON-TARGETLUNGLEFTCT SCANINVESTIGATOR1SCREENING2026-01-05
TUYAMAA-014NEW01TUMIDENTTumor IdentificationNEWNEWADRENAL GLANDRIGHTCT SCANINVESTIGATOR4WEEK 122026-03-30
TUYAMAA-011T01TUMIDENTTumor IdentificationTARGETTARGETLIVERLEFTCT SCANINVESTIGATOR1SCREENING2026-01-12
TUYAMAA-012NT01TUMIDENTTumor IdentificationNON-TARGETNON-TARGETBONE—CT SCANINVESTIGATOR1SCREENING2026-01-12
Shaded columns are derived— = missing value

Comments and assessment materials

Comments

Signed in with GitHub; saved in repository Discussions

Mapping spec

Generated from the benchmark YAML; do not edit by hand

Variable NameVariable LabelTypeLengthControlled Terms or FormatOriginCoreConversion DefinitionVariable TypeVariable OrderComments for Define
DOMAINDomain AbbreviationCharAssignedSet constant value "TU".SDTM1
STUDYIDStudy IdentifierCharCollectedCopy value from TU_RAW.STUDYID.SDTM2
USUBJIDUnique Subject IdentifierCharCollectedCopy value from TU_RAW.USUBJID.SDTM3
TUSEQSequence NumberNumCollectedCopy value from TU_RAW.TUSEQ.SDTM4
TULNKIDLink IDCharDerivedIf TU_RAW.LESION_CATEGORY = 'Target' then fill the template "T{TU_RAW.LESION_NUM}"; If TU_RAW.LESION_CATEGORY = 'Non-target' then fill the template "NT{TU_RAW.LESION_NUM}"; If TU_RAW.LESION_CATEGORY = 'New' then fill the template "NEW{TU_RAW.LESION_NUM}"; otherwise blank.SDTM5
TUTESTCDTumor Identification Test Short NameCharTUMIDENTAssignedSet constant value "TUMIDENT".SDTM6
TUTESTTumor Identification Test NameCharAssignedSet constant value "Tumor Identification".SDTM7
TUORRESTumor Identification ResultCharTARGET, NON-TARGET, NEWDerivedConvert TU_RAW.LESION_CATEGORY to upper case.SDTM8
TUSTRESCTumor Identification Result in Std FormatCharDerivedCopy value from TUORRES.SDTM9
TULOCLocation of the TumorCharDerivedConvert TU_RAW.LOCATION to upper case.SDTM10
TULATLateralityCharDerivedConvert TU_RAW.LATERALITY to upper case; a missing source → blank.SDTM11
TUMETHODMethod of IdentificationCharCollectedCopy value from TU_RAW.METHOD.SDTM12
TUEVALEvaluatorCharCollectedCopy value from TU_RAW.EVALUATOR.SDTM13
VISITNUMVisit NumberNumCollectedCopy value from TU_RAW.VISITNUM.SDTM14
VISITVisit NameCharCollectedCopy value from TU_RAW.VISIT.SDTM15
TUDTCDate/Time of Tumor IdentificationCharISO 8601CollectedCopy value from TU_RAW.TUDTC.SDTM16
VariablePermitted values
TUTESTCDTUMIDENT
TUORRESTARGET, NON-TARGET, NEW
VersionDateAuthorDescriptionReviewerSign-off
1.32026-09-29yamaa docs buildShow study codelist names, external dictionaries, and ISO 8601 formats in variable rows; list the document's codelist values and metadata
1.22026-09-29yamaa docs buildClassify ADaM copies from a declared input as Predecessor and recodes as Derived, and SDTM recodes of locally derived columns as Derived
1.12026-09-29yamaa docs buildResolve lookups into the donor record they select, and give every derivation shape a plain-language rule instead of its raw YAML
1.0yamaa docs buildInitial generation from spec.yaml

Agent prompt

The request an agent receives with the input files; each tier states no more than the one above

prompts/sdtm-tu-tumor-identification/full.md

Edit
27 lines

Following CDISC SDTM standards, use the provided TU_RAW dataset to create a TU dataset with one record per identified tumor or lesion.

The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, TUSEQ, TULNKID, TUTESTCD, TUTEST, TUORRES, TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, VISIT, TUDTC

TUSEQ numbers a subject's identification records in collection order, starting at 1. TULNKID ties the lesion to its assessments in the tumor results domain: T plus the lesion number for a target lesion, NT plus the number for a non-target lesion, and NEW plus the number for a new lesion, the number written in two digits as collected (target lesion 3 is T03). TUTESTCD is TUMIDENT and TUTEST is Tumor Identification on every record. TUORRES is the lesion category as collected, standardized to TARGET, NON-TARGET, or NEW; TUSTRESC repeats the standardized category. TULOC is the anatomical location as collected, standardized to uppercase. TULAT is the laterality as collected, standardized to LEFT or RIGHT, and has no value when the site recorded none. TUMETHOD, TUEVAL, VISITNUM, and TUDTC are as collected.

A lymph-node target lesion is identified like any other target lesion: it keeps a T link identifier and its category stays TARGET, while its location names it as a lymph node. A new lesion is identified once, at the visit where it first appears.

Read the source datasets from /app/input and save the completed dataset as /app/output/tu.csv.

prompts/sdtm-tu-tumor-identification/conventions.md

Edit
16 lines

Following CDISC SDTM standards, use the provided TU_RAW dataset to create a TU dataset with one record per identified tumor or lesion.

The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, TUSEQ, TULNKID, TUTESTCD, TUTEST, TUORRES, TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, VISIT, TUDTC

TULNKID is T plus the lesion number for a target lesion, NT plus the number for a non-target lesion, and NEW plus the number for a new lesion, the number written in two digits as collected (target lesion 3 is T03). TUTESTCD is TUMIDENT and TUTEST is Tumor Identification on every record. TUORRES is standardized to TARGET, NON-TARGET, or NEW. TULOC is standardized to uppercase. TULAT is standardized to LEFT or RIGHT, or has no value.

Read the source datasets from /app/input and save the completed dataset as /app/output/tu.csv.

prompts/sdtm-tu-tumor-identification/brief.md

Edit
9 lines

Following CDISC SDTM standards, use the provided TU_RAW dataset to create a TU dataset with one record per identified tumor or lesion.

The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, TUSEQ, TULNKID, TUTESTCD, TUTEST, TUORRES, TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, VISIT, TUDTC

Read the source datasets from /app/input and save the completed dataset as /app/output/tu.csv.

yamaa code

Runs the yamaa specification; its result must match the expected output

run.R

Edit
4 lines
library(yamaa)tu <- yamaa_domain("spec.yaml")$outputtu

run.py

Edit
4 lines
import yamaatu = yamaa.yamaa_domain("spec.yaml").outputtu

Solution without yamaa

Written from the full prompt and the inputs alone; CI checks it reproduces the expected output

solutions/sdtm-tu-tumor-identification/result.R

Edit
48 lines
# Reference solution for the yamaa benchmark sdtm-tu-tumor-identification (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(stringr)raw <- read_csv(  "/app/input/tu_raw.csv",  col_types = cols(    TUSEQ = col_integer(),    VISITNUM = col_integer(),    .default = col_character()  ))tu <- raw |>  mutate(    DOMAIN = "TU",    TULNKID = case_when(      LESION_CATEGORY == "Target" ~ paste0("T", LESION_NUM),      LESION_CATEGORY == "Non-target" ~ paste0("NT", LESION_NUM),      .default = paste0("NEW", LESION_NUM)    ),    TUTESTCD = "TUMIDENT",    TUTEST = "Tumor Identification",    TUORRES = case_when(      LESION_CATEGORY == "Target" ~ "TARGET",      LESION_CATEGORY == "Non-target" ~ "NON-TARGET",      .default = "NEW"    ),    TUSTRESC = TUORRES,    TULOC = str_to_upper(LOCATION),    TULAT = str_to_upper(LATERALITY),    TUMETHOD = METHOD,    TUEVAL = EVALUATOR  ) |>  arrange(USUBJID, TUSEQ) |>  select(    DOMAIN, STUDYID, USUBJID, TUSEQ, TULNKID, TUTESTCD, TUTEST, TUORRES,    TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, VISIT, TUDTC  )dir.create("/app/output", showWarnings = FALSE)write_csv(tu, "/app/output/tu.csv", na = "")

solutions/sdtm-tu-tumor-identification/result.py

Edit
66 lines
# Reference solution for the yamaa benchmark sdtm-tu-tumor-identification (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 plraw = pl.read_csv("/app/input/tu_raw.csv", infer_schema=False).with_columns(    pl.col("TUSEQ").cast(pl.Int64),    pl.col("VISITNUM").cast(pl.Int64),)prefix = (    pl.when(pl.col("LESION_CATEGORY") == "Target")    .then(pl.lit("T"))    .when(pl.col("LESION_CATEGORY") == "Non-target")    .then(pl.lit("NT"))    .otherwise(pl.lit("NEW")))category = (    pl.when(pl.col("LESION_CATEGORY") == "Target")    .then(pl.lit("TARGET"))    .when(pl.col("LESION_CATEGORY") == "Non-target")    .then(pl.lit("NON-TARGET"))    .otherwise(pl.lit("NEW")))tu = (    raw.with_columns(        DOMAIN=pl.lit("TU"),        TULNKID=prefix + pl.col("LESION_NUM"),        TUTESTCD=pl.lit("TUMIDENT"),        TUTEST=pl.lit("Tumor Identification"),        TUORRES=category,        TUSTRESC=category,        TULOC=pl.col("LOCATION").str.to_uppercase(),        TULAT=pl.col("LATERALITY").str.to_uppercase(),        TUMETHOD=pl.col("METHOD"),        TUEVAL=pl.col("EVALUATOR"),    )    .sort(["USUBJID", "TUSEQ"])    .select(        "DOMAIN",        "STUDYID",        "USUBJID",        "TUSEQ",        "TULNKID",        "TUTESTCD",        "TUTEST",        "TUORRES",        "TUSTRESC",        "TULOC",        "TULAT",        "TUMETHOD",        "TUEVAL",        "VISITNUM",        "VISIT",        "TUDTC",    ))Path("/app/output").mkdir(exist_ok=True)tu.write_csv("/app/output/tu.csv")

solutions/sdtm-tu-tumor-identification/result.sas

Edit
16 lines
/* opensas reference solution for the yamaa benchmark sdtm-tu-tumor-identification.   Reads the benchmark inputs and derives the requested output.   Execute with the existing opensas runtime: opensas /app/output/result.sas. */data tu_raw;  length STUDYID USUBJID LESION_CATEGORY LESION_NUM LOCATION LATERALITY METHOD EVALUATOR VISIT TUDTC $1024;  infile "/app/input/tu_raw.csv" dsd dlm="," firstobs=2 truncover lrecl=32767;  input STUDYID : $char1024. USUBJID : $char1024. TUSEQ LESION_CATEGORY : $char1024. LESION_NUM : $char1024. LOCATION : $char1024. LATERALITY : $char1024. METHOD : $char1024. EVALUATOR : $char1024. VISITNUM VISIT : $char1024. TUDTC : $char1024.;run;data result; set tu_raw; length DOMAIN $2 TULNKID TUTESTCD TUTEST TUORRES TUSTRESC TULOC TULAT TUMETHOD TUEVAL PREFIX $1024;DOMAIN='TU'; TUORRES=upcase(LESION_CATEGORY); TUSTRESC=TUORRES; TUTESTCD='TUMIDENT'; TUTEST='Tumor Identification'; TULOC=upcase(LOCATION); TULAT=upcase(LATERALITY); TUMETHOD=METHOD; TUEVAL=EVALUATOR; PREFIX='NEW'; if TUORRES='TARGET' then PREFIX='T'; if TUORRES='NON-TARGET' then PREFIX='NT'; TULNKID=cats(PREFIX,put(input(LESION_NUM,best32.),z2.)); run;proc sql;  create table final as select DOMAIN, STUDYID, USUBJID, TUSEQ, TULNKID, TUTESTCD, TUTEST, TUORRES, TUSTRESC, TULOC, TULAT, TUMETHOD, TUEVAL, VISITNUM, VISIT, TUDTC from result;quit;proc export data=final outfile="/app/output/tu.csv" dbms=csv replace; run;