Rule index¶
Rule IDs identify rules independently of file paths. A card's ID carries its file's prefix.
Rule cards¶
| Rule | Title | File |
|---|---|---|
| SPEC-1 | A specification derives one output dataset from the root fields it declares | specification.md |
| SPEC-2 | Mapping keys, dataset identifiers, column names and row IDs are each unique | specification.md |
| SPEC-3 | The artifact's columns are declared, never generated from source fields | specification.md |
| SPEC-4 | Every declared column is derived, never filled from a same-named source variable | specification.md |
| SPEC-5 | A column without a column-level derivation is derived in every row template | specification.md |
| SPEC-6 | A row-local column-level derivation is a default that each row template may override | specification.md |
| SPEC-7 | A declared column outside output.columns is internal and is evaluated like an output column |
specification.md |
| SPEC-9 | A copy entry declares the listed columns of a schema-linked input under their names, with the producer's type and label |
specification.md |
| SPEC-8 | Language source is ASCII | specification.md |
| LAYER-1 | A specification is its entry file composed with the chain of parents and the fragments it reaches | inheritance.md |
| LAYER-2 | A parent or a fragment is one local YAML file resolved from the layer that names it | inheritance.md |
| LAYER-3 | Layers contribute from the root ancestor to the entry, each after its fragments, later layers taking precedence | inheritance.md |
| LAYER-4 | Every layer is a valid partial specification of the language version it declares | inheritance.md |
| LAYER-5 | Keyed collections compose member by member, the blocks output and submission field by field, and every other root field replaces whole |
inheritance.md |
| LAYER-6 | A matching member merges recursively: classes by field, mappings by key, scalars and lists by replacement | inheritance.md |
| LAYER-7 | Requiredness and defaults apply to the composed member, never to one contribution | inheritance.md |
| LAYER-8 | A named window composes by name like every keyed member, and every reference uses the final definition | inheritance.md |
| LAYER-9 | YAML null is the missing value, and a layer clears an inherited field only by listing it in clear |
inheritance.md |
| LAYER-10 | A path keeps its declaring layer's base and authored spelling | inheritance.md |
| LAYER-11 | Declarations that cannot affect the artifact or an assertion are pruned | inheritance.md |
| LAYER-12 | Name and reference validation applies after pruning | inheritance.md |
| LAYER-13 | A layered specification's resolved columns follow dependency order with a stable tie-break | inheritance.md |
| LAYER-14 | The resolved specification is canonical | inheritance.md |
| NAME-1 | input declares every dataset a specification reads, each under its own identifier |
names.md |
| NAME-2 | No input dataset takes the output dataset's name | names.md |
| NAME-3 | A qualified name reads a declared dataset or lookup, and a bare name reads an output column | names.md |
| NAME-4 | A qualified read of the driver reads its current record, or in a group the group's key | names.md |
| NAME-5 | A variable field names exactly one variable, never an expression |
names.md |
| NAME-6 | A structured source adds handlers and a record filter to one variable |
names.md |
| NAME-7 | An odm expression reads one collected item named as DATASET.ItemOID |
names.md |
| NAME-8 | An ODM input binds its eleven fixed text fields by case-folded name, checked at validation | names.md |
| NAME-9 | Every ODM input record carries the seven required identifiers | names.md |
| NAME-10 | A row's ODM scope is the set of ODM input records the row was built from | names.md |
| NAME-11 | An odm expression evaluates only for a row whose ODM scope covers the input it names |
names.md |
| NAME-12 | An odm read identifies the scope records of its item that meet its OID lists and filter |
names.md |
| NAME-13 | An odm read gives the identified record's Value, missing for none, and fails for several |
names.md |
| VALUE-1 | A column declares exactly one of six types, and every type also admits missing | values.md |
| VALUE-2 | An operation never converts its inputs, and an input of an incompatible type fails | values.md |
| VALUE-3 | A completed result converts to its column's type by one table, or fails | values.md |
| VALUE-24 | A derivation whose result type can never convert to its declared type fails validation | values.md |
| VALUE-25 | Missing is one value distinct from every other, and each operation states what it does with it | values.md |
| VALUE-4 | A non-finite float becomes missing before any consumer can see it | values.md |
| VALUE-5 | An int is a signed 64-bit integer, and leaving that range fails with integer_overflow | values.md |
| VALUE-6 | Numeric text parses by one grammar, and every other spelling fails | values.md |
| VALUE-7 | Conversion to int succeeds only for an exactly integral value within range | values.md |
| VALUE-8 | An int widens to the nearest binary64, and a number converts to one canonical text | values.md |
| VALUE-9 | Values are used unrounded, and presentation rounding never feeds back | values.md |
| VALUE-10 | Each arithmetic operator and numeric function returns a fixed numeric type | values.md |
| VALUE-11 | A string is a sequence of Unicode scalar values, decoded strictly where it enters | values.md |
| VALUE-12 | Text is never normalized, and two strings are equal only scalar for scalar | values.md |
| VALUE-13 | A date names one calendar day, a datetime one civil second and a time one second of the day, with no gaps | values.md |
| VALUE-14 | A datetime carries no zone, offset or fractional second, and never shifts implicitly | values.md |
| VALUE-15 | Text becomes a date, datetime or time only in one zero-padded extended form | values.md |
| VALUE-16 | Every temporal value is complete and records its collected precision on one ladder | values.md |
| VALUE-17 | A temporal value is written in one canonical text that carries its fields alone | values.md |
| VALUE-18 | A date, a datetime and a time never convert into one another or enter arithmetic | values.md |
| VALUE-19 | An int and a float compare exactly; every other type compares only with itself | values.md |
| VALUE-20 | Strings order by scalar value, position by position | values.md |
| VALUE-21 | Values of one temporal type order chronologically, whatever their collected precision | values.md |
| VALUE-22 | An order term sorts by its type's order and direction, and missing sorts lowest unless nulls places it | values.md |
| VALUE-23 | Rows equal on every order term keep their construction order | values.md |
| INPUT-1 | The input path's extension selects the profile that reads it, and nothing is sniffed | inputs.md |
| INPUT-2 | A reader returns records in stored order, and nothing reorders them | inputs.md |
| INPUT-3 | An input may declare a generated field holding each record's one-based stored position | inputs.md |
| INPUT-4 | A generated ordinal must not collide with a stored field or join an ODM input | inputs.md |
| INPUT-5 | Every input field has one type, from its container or its declaration, never from its values | inputs.md |
| INPUT-6 | A types entry may only type an existing field of a source that supplies no type | inputs.md |
| INPUT-7 | Stored text parses into its field's declared type, or fails ingestion before any derivation | inputs.md |
| INPUT-8 | A null or an empty field is missing, and no other text spells missing | inputs.md |
| INPUT-9 | Each input declares whether a stored empty string is missing or present | inputs.md |
| INPUT-10 | A schema link types a stored artifact from its producing specification without running it | inputs.md |
| INPUT-11 | A linked artifact's fields are exactly its producer's output columns, with their types | inputs.md |
| ROW-1 | Each row template has a unique id and builds its rows from one declared driver | rows.md |
| ROW-2 | An intermediate drives rows only when it reads an input and exposes typed fields | rows.md |
| ROW-3 | A row template without group_by is record-driven and builds one candidate row per driver record | rows.md |
| ROW-4 | A row template with group_by builds one candidate row per group of driver records, then filters it | rows.md |
| ROW-5 | A grouped row derivation reads a driver field only as a group key or through an aggregate | rows.md |
| ROW-6 | A row filter names only columns its row template derives, and only values complete at its phase | rows.md |
| ROW-7 | Row templates are ordered sections, and each retained driver record or group yields one row | rows.md |
| ROW-8 | Without row templates, the output rows are the distinct key combinations of the base records | rows.md |
| ROW-9 | A root filter selects base records before the distinct-keys step and reads only base fields | rows.md |
| COLUMN-1 | A run validates, builds rows, derives columns, verifies, orders and publishes, in that order | columns.md |
| COLUMN-2 | A column derivation yields exactly one value per row and never changes the row count | columns.md |
| COLUMN-3 | Dependencies come from every reference an expression makes, closed grammars included | columns.md |
| COLUMN-4 | Row derivations follow their template's dependency graph and never read a value only column derivation produces | columns.md |
| COLUMN-5 | Columns follow declaration order except for causal backward row reads | columns.md |
| COLUMN-6 | A column dependency cycle fails unless every cycle crosses a causal backward row read | columns.md |
| COLUMN-7 | Without row templates, a key is computed from one base record and never from a non-key output column | columns.md |
| COLUMN-8 | Every derived value is evaluated, converted and handled before anything reads it, then verified | columns.md |
| COLUMN-9 | A row filter reads candidate values after stages 1 to 3 and never hides a failed derivation | columns.md |
| COLUMN-10 | A local handler answers its condition with a literal, and an omitted handler gives missing for a missing single input or absent record and leaves every other condition fatal | columns.md |
| COLUMN-11 | absent answers a lookup that finds no record, and missing answers a missing input value |
columns.md |
| COLUMN-12 | A structured source carries its own handlers, and order_by with keep selects one of several records | columns.md |
| COLUMN-13 | A result wrapper's unconvertible replaces only a failed conversion to the column type | columns.md |
| COLUMN-14 | Every handler path reports how many records it answered as a report row, default substitutions and zero included | columns.md |
| COLUMN-15 | A language diagnostic cites the rule that owns its failure; only listed implementation conditions cite none | columns.md |
| COLUMN-16 | Every condition reports one phase from a closed list, which names the part of the run that decides it | columns.md |
| EXPR-1 | A derivation holds exactly one registered expression keyword, which owns its payload | expressions.md |
| EXPR-2 | An expression yields one value per row, and only windows and aggregates read other rows | expressions.md |
| EXPR-3 | Expressions nest only in case results, key match values and a nearest selection's to |
expressions.md |
| EXPR-14 | Every expression has one declared result type function, and every context reads its type | expressions.md |
| EXPR-4 | A reference or a structured source copies a named variable, and a literal returns its value unchanged | expressions.md |
| EXPR-5 | An expression field reads a bare name as a reference and quoted text as a literal | expressions.md |
| EXPR-6 | An expression that selects a value returns it unchanged, with its collected precision | expressions.md |
| EXPR-7 | case returns the value of its first TRUE branch, then otherwise, else missing | expressions.md |
| EXPR-8 | flag returns a declared value for each of TRUE, FALSE and UNKNOWN | expressions.md |
| EXPR-9 | first_available returns the first source that is not missing | expressions.md |
| EXPR-10 | greatest and least return the largest or smallest non-missing source | expressions.md |
| EXPR-11 | mapping replaces a string source with its dictionary value | expressions.md |
| EXPR-12 | A case-insensitive mapping folds ASCII letters, and its folded keys must be unique | expressions.md |
| EXPR-15 | decode replaces a coded source with its item's decode in a codelist the project file declares | expressions.md |
| EXPR-13 | cut assigns a numeric source to one of its labeled break intervals | expressions.md |
| FORMULA-1 | An expression is one text in the closed expression grammar | formulas.md |
| FORMULA-2 | Keywords and the names of functions and reducers are case-insensitive, and a sign binds tightest and OR loosest | formulas.md |
| FORMULA-3 | A literal has a fixed runtime type, an integer literal fits int, and a temporal literal needs its keyword | formulas.md |
| FORMULA-27 | The field an expression is written in fixes its root and the constructs it admits | formulas.md |
| FORMULA-9 | An identifier names a value visible at its site, and any other name fails | formulas.md |
| FORMULA-4 | A predicate is TRUE, FALSE or UNKNOWN, and only TRUE retains a row or record | formulas.md |
| FORMULA-5 | Two non-missing operands compare only when their runtime types are mutually comparable | formulas.md |
| FORMULA-6 | IN and BETWEEN expand into comparisons, and their NOT forms negate the result | formulas.md |
| FORMULA-7 | LIKE matches text scalar by scalar, case-sensitively, with an optional one-scalar ESCAPE | formulas.md |
| FORMULA-8 | str_contains is the one truth-valued function and searches its source for a portable regex | formulas.md |
| FORMULA-12 | Every operand of arithmetic or of a numeric function must be numeric | formulas.md |
| FORMULA-13 | The numeric functions are a closed list, each with a fixed argument count | formulas.md |
| FORMULA-14 | A missing operand makes arithmetic and numeric functions missing, except NULLIF's second argument | formulas.md |
| FORMULA-15 | Division by zero, an invalid root, logarithm, power or probability, and int overflow fail the run | formulas.md |
| FORMULA-16 | There is one rounding: half away from zero, with near ties treated as ties | formulas.md |
| FORMULA-17 | aggregate reduces one relation to one value with a closed reducer expression | formulas.md |
| FORMULA-18 | The reducers are exactly SUM, COUNT, MIN, MAX, MEAN, ONLY, STR_JOIN, MEDIAN, Q1, Q3, QUANTILE, STDDEV, VARIANCE and GEOMEAN | formulas.md |
| FORMULA-19 | SUM adds in relation record order, MEAN divides that SUM by COUNT, and VARIANCE, STDDEV and GEOMEAN add in the same order | formulas.md |
| FORMULA-20 | ONLY returns the value of a group's one record and fails on more than one | formulas.md |
| FORMULA-21 | Reductions do not nest | formulas.md |
| FORMULA-22 | An identifier outside a reduction must name a grouping column | formulas.md |
| FORMULA-23 | A reduction keeps the type it reduces, and arithmetic over reductions is numeric | formulas.md |
| FORMULA-24 | Value reducers skip missing values, and a group with no record reduces to missing | formulas.md |
| FORMULA-26 | Expressions evaluate deterministically and exactly as written | formulas.md |
| LOOKUP-25 | Every lookup runs the same four steps, match, narrow, select and answer absence, whatever its kind | lookup.md |
| LOOKUP-9 | Match keeps the records whose keys equal the current row's match values and whose bounds hold its range value | lookup.md |
| LOOKUP-8 | Narrow keeps the matched records for which the lookup's filter is TRUE | lookup.md |
| LOOKUP-10 | Select chooses the first or last candidate by order_by, and an aggregate reduces every candidate | lookup.md |
| LOOKUP-26 | A named intermediate's nearest selection chooses the candidate whose date or datetime lies nearest the current row's reference | lookup.md |
| LOOKUP-28 | A named intermediate's pivot exposes each listed value of one donor field as a field of its selection | lookup.md |
| LOOKUP-24 | A lookup with no candidate answers absence, missing by default, unless require_match fails it | lookup.md |
| LOOKUP-14 | Lookup handler counts, failures and reviews report the match in one vocabulary | lookup.md |
| LOOKUP-5 | A key pairs each column of the lookup's relation with a current-row match value | lookup.md |
| LOOKUP-6 | A key match value may be an expression whose static result type is checked before matching | lookup.md |
| LOOKUP-1 | A dataset-qualified source reads through the implicit join on the input's declared key | lookup.md |
| LOOKUP-2 | Row construction reads another dataset through the same join, using only values available before column derivation | lookup.md |
| LOOKUP-3 | A named intermediate declares an id, a dataset and a key | lookup.md |
| LOOKUP-4 | A named intermediate must narrow, derive or reshape its dataset | lookup.md |
| LOOKUP-7 | A named intermediate may read SELF, the completed rows of earlier row templates | lookup.md |
| LOOKUP-11 | A lookup-qualified variable reads a column of the selected record | lookup.md |
| LOOKUP-12 | A lookup matches once per row when first read and never changes the row count | lookup.md |
| LOOKUP-15 | Intermediate derivations add per-record fields to the donor records | lookup.md |
| LOOKUP-16 | An intermediate derivation may read another intermediate's selection for its donor record | lookup.md |
| LOOKUP-17 | An intermediate's unique verification asserts that no donor column combination repeats, warning instead only where a selection chooses | lookup.md |
| LOOKUP-18 | An aggregate reduces one declared dataset, the constructed output rows, or the current input group | lookup.md |
| LOOKUP-19 | A qualified aggregate groups by output keys and an unqualified one by output columns | lookup.md |
| LOOKUP-22 | A qualified aggregate's derivations compute typed per-record values before reduction | lookup.md |
| LOOKUP-27 | A named intermediate that writes inner_join is a pair relation, one record for each matching pair of its two sides | lookup.md |
| WINDOW-1 | A window reference names one complete definition declared in root windows | windows.md |
| WINDOW-2 | A named reference expands to an independent copy of its definition before analysis | windows.md |
| WINDOW-3 | A window partitions the rows of its evaluation context by group_by and preserves row count | windows.md |
| WINDOW-11 | A column-level window reads a driver field only when every row template has that driver | windows.md |
| WINDOW-4 | A window filter excludes rows before partitioning, and an excluded row receives missing | windows.md |
| WINDOW-5 | Positional window operations require window.order_by, and baseline_flag defaults it to its date | windows.md |
| WINDOW-6 | row_number numbers positions from 1, and rank gives rows tied on every term one number | windows.md |
| WINDOW-7 | row_value reads the source from the row a nonzero offset away along the declared order | windows.md |
| WINDOW-12 | Strictly backward row_value reads can carry calculated history in one independently ordered column group | windows.md |
| WINDOW-8 | locf carries the closest strictly earlier non-missing source forward unless include_current lets a present current source answer | windows.md |
| WINDOW-9 | baseline_flag flags the last eligible row of each partition in date order, and a tie for last fails | windows.md |
| WINDOW-10 | Window operations convert nothing: numbering returns int and selections keep their type | windows.md |
| TEXT-1 | Text verbs take string sources and fail rather than convert another type | text.md |
| TEXT-2 | str_pad left-pads a value's canonical text with ASCII spaces to a minimum width | text.md |
| TEXT-13 | str_substr takes the scalars of a text from a position counted from 1, and gives missing past its end | text.md |
| TEXT-16 | str_substr with piece breaks a text between words into pieces of at most length scalars and takes one | text.md |
| TEXT-14 | str_length counts the scalar values of a text as an int | text.md |
| TEXT-15 | str_decimal writes a number with exactly decimals digits by the one rounding, left-padded with spaces to a minimum width |
text.md |
| TEXT-3 | A string template is literal text, braced placeholders and doubled braces, nothing else | text.md |
| TEXT-4 | str_template replaces each placeholder with its string value, or answers a missing one | text.md |
| TEXT-5 | str_case changes the case of ASCII letters only, one scalar for one | text.md |
| TEXT-6 | Every pattern is a portable ECMA-262 subset without lookaround or backreferences | text.md |
| TEXT-7 | A pattern carries the Unicode flag only: case-sensitive, anchored to the whole subject, stateless | text.md |
| TEXT-8 | Character classes are fixed ASCII and ECMA-262 sets, and a non-ASCII scalar is an escape | text.md |
| TEXT-9 | A schema pattern is a full match, while matches and str_extract search the subject | text.md |
| TEXT-10 | Capture groups are numbered by opening parenthesis, and str_extract returns one group | text.md |
| TEXT-11 | str_replace replaces every non-overlapping match, left to right, with literal text | text.md |
| TEXT-12 | A pattern too deep or too large to compile is refused at its path; matching is never refused | text.md |
| TIME-1 | Each temporal operation has fixed input types, and a type-dispatched one declares its type | temporal.md |
| TIME-2 | to_date returns the calendar date of a datetime or of text carrying a complete date, and partial text gives missing | temporal.md |
| TIME-3 | to_epoch_day converts a date to its signed day count from 1970-01-01 | temporal.md |
| TIME-20 | time_of_day returns a datetime's time of day as whole seconds since midnight | temporal.md |
| TIME-23 | to_time returns a datetime's time of day as a time | temporal.md |
| TIME-4 | diff returns end minus start in whole calendar units for dates, or in an elapsed unit for datetimes | temporal.md |
| TIME-5 | closed sets which endpoints a day count between two dates includes, and only that count takes it |
temporal.md |
| TIME-6 | study_day counts from the reference date as day 1, with no day zero | temporal.md |
| TIME-7 | Collected date text is ISO 8601 read up to its first unknown field, and precision reports how much of the declared type a source carries | temporal.md |
| TIME-22 | date_text reads text in one of its declared date forms into the collected date text it denotes | temporal.md |
| TIME-19 | dtc writes collected date parts as collected date text that stops before the first missing part | temporal.md |
| TIME-8 | impute completes collected text into a value of its declared type from declared month, day and time rules | temporal.md |
| TIME-9 | Imputation bounds move only supplied fields, a bound outside the collected interval is ignored, and crossed bounds give not_after | temporal.md |
| TIME-10 | impute's month and day rules must fit each other and the calendar | temporal.md |
| TIME-13 | A missing source gives missing unless impute declares a fallback, and invalid text fails unless invalid answers it | temporal.md |
| TIME-14 | shift moves a date by whole days, or a datetime by a signed elapsed amount rounded to a whole second | temporal.md |
| TIME-17 | duration_value reads ISO 8601 fixed-length duration text as a number in a declared unit | temporal.md |
| TIME-21 | duration_text writes a number in a declared unit as canonical ISO 8601 fixed-length duration text | temporal.md |
| TIME-24 | calendar_duration writes the whole months from one date to another, then the remaining days, as ISO 8601 duration text | temporal.md |
| TIME-18 | imputation_flag returns the ADaM date or time imputation flag from an imputed value's collected precision | temporal.md |
| CHECK-1 | Column checks run after their column converts; dataset checks run after all column work | verification.md |
| CHECK-2 | A failed error verification fails the run; a violated warning fails nothing and changes no row | verification.md |
| CHECK-3 | A verification may declare a nonempty id, unique within its verification list | verification.md |
| CHECK-4 | A verification declares known fields, ordered bounds and existing columns of a compatible type | verification.md |
| CHECK-5 | Only not_missing rejects a missing value, on the rows its when selects and beyond any share its max_fraction allows, and declaring it on a key column is redundant |
verification.md |
| CHECK-6 | allowed_values requires every present value to equal one listed value |
verification.md |
| CHECK-7 | range requires every present numeric value to lie within its inclusive bounds |
verification.md |
| CHECK-8 | max_length bounds a string column's values by their count of Unicode scalar values |
verification.md |
| CHECK-9 | matches requires every present string to match its regular expression |
verification.md |
| CHECK-10 | unique requires the combined values of a column set other than the keys to be unique, missing values included |
verification.md |
| CHECK-11 | all_or_none requires the listed values of each row to be all missing or all present |
verification.md |
| CHECK-12 | assert requires its predicate to be TRUE on every output row its when does not exempt |
verification.md |
| CHECK-13 | row_count bounds how many output rows its filter admits, as a count and as a share |
verification.md |
| CHECK-14 | Row count bounds apply to every group of the artifact's rows that its when does not exempt | verification.md |
| CHECK-15 | An ordered-series assertion is a derivation followed by a row-wise assertion | verification.md |
| CHECK-16 | A cross-dataset link is asserted by the derivation that produces it, not by a verification | verification.md |
| CHECK-22 | Every run builds one report, which a warning requires a file for and a failed run still writes | verification.md |
| CHECK-23 | The report has one row per run, input dataset, row template, handler path, output column and evaluated check, in that order | verification.md |
| CHECK-24 | The report has fourteen fixed columns, and a kind leaves missing each column it has no value for | verification.md |
| CHECK-25 | KEYS and DETAILS are compact ASCII JSON with names in text order | verification.md |
| CHECK-26 | The report is verified before it is written or returned, and a malformed report is an execution defect | verification.md |
| OUTPUT-1 | The artifact's columns are exactly output.columns, in that order |
output.md |
| OUTPUT-2 | keys lists one or more output columns, each once |
output.md |
| OUTPUT-3 | Every artifact row's combined key values are non-missing and unique | output.md |
| OUTPUT-4 | output.path is required and names the primary file |
output.md |
| OUTPUT-5 | Each output path's extension selects the csv or parquet profile from a closed mapping |
output.md |
| OUTPUT-6 | A profile carries every value the language admits without changing it | output.md |
| OUTPUT-7 | A run publishes once, after the whole artifact is complete | output.md |
| OUTPUT-8 | Each file replaces its target atomically, and a failed run leaves the target unchanged | output.md |
| OUTPUT-9 | The primary file and the report file have distinct paths, each selecting its own profile | output.md |
| OUTPUT-10 | The report file publishes before the primary file, and a failed run publishes only its report | output.md |
| OUTPUT-11 | output.order_by orders the artifact's rows once, after every verification |
output.md |
| OUTPUT-12 | Each output.order_by term names a different declared column |
output.md |
| LIMIT-1 | A size past a fixed limit refuses its operation as engine_rejected, naming the boundary, its limit and the observed size | limits.md |
| LIMIT-2 | One fixed policy bounds each file, table, declaration, pattern and built text | limits.md |
| LIMIT-3 | A build run over key-bounded partitions gives the whole-table run's result, and its row and cell limits bound each partition | limits.md |
| FILE-1 | A document's relative paths resolve from the file that declares them, never from a discovered root | reference/files.md |
| FILE-2 | relative_to selects the declaring file's or the entry file's directory as a relative path's base |
reference/files.md |
| FILE-3 | A schema-linked artifact is an ordinary input at its own path, and its producer is never run | reference/files.md |
| FILE-4 | A path is relative or rooted, decided from its text before the filesystem is consulted | reference/files.md |
| FILE-5 | A path has no URI scheme, backslash, empty segment or trailing separator | reference/files.md |
| FILE-6 | . and .. segments resolve textually from the base and may leave it |
reference/files.md |
| FILE-7 | Resolution walks each component from a directory anchor and must reach one regular file | reference/files.md |
| FILE-8 | No component below the anchor is a symbolic link | reference/files.md |
| FILE-9 | A run reads one immutable byte snapshot of each physical file, whatever spelling reaches it | reference/files.md |
| FILE-10 | Content that changes between validation and ingestion fails the run | reference/files.md |
| FILE-11 | A path failure names the written path and declaring field and reports exactly one condition | reference/files.md |
| CSV-1 | A csv artifact is UTF-8 without a byte-order mark, and every record ends in a line feed | reference/csv.md |
| CSV-2 | The header names output.columns in order, and each row follows as one record |
reference/csv.md |
| CSV-3 | A field is quoted exactly when it is empty or contains a quote, comma, U+000D or U+000A |
reference/csv.md |
| CSV-4 | Missing is written as an empty bare field and the empty string as two quote characters | reference/csv.md |
| CSV-5 | Each value is written as the canonical text of its column type | reference/csv.md |
| CSV-6 | output.decimals is an integer from 0 to 18 for every float column of a csv artifact |
reference/csv.md |
| CSV-7 | With output.decimals of n, every float is written in fixed point with exactly n decimal digits |
reference/csv.md |
| CSV-8 | Display rounding happens once, when a field is written, and no other stage sees it | reference/csv.md |
| CSV-9 | Display rounding applies the one rounding to the exact binary64 value | reference/csv.md |
| CSV-10 | A csv source is UTF-8, with a byte-order mark only where its input declares one | reference/csv.md |
| CSV-11 | A record ends in U+000A, optionally preceded by U+000D, the last may end the file, and blank lines that end the file are no record |
reference/csv.md |
| CSV-12 | Fields are separated by commas and are either bare or quoted, with nothing trimmed | reference/csv.md |
| CSV-13 | The header names each field once, and every later record has exactly that many fields | reference/csv.md |
| CSV-14 | A field reaches ingestion as its text, or as missing when it has no characters | reference/csv.md |
| CSV-15 | No reader option changes what the csv profile fixes, and a reader repairs nothing | reference/csv.md |
| CSV-16 | A csv reading failure names the dataset, the written path, and the record and field | reference/csv.md |
| PARQUET-1 | Each column type maps to exactly one Parquet physical and logical type | reference/parquet.md |
| PARQUET-2 | A date counts days from 1970-01-01, and a datetime and a time whole-second microseconds from 1970-01-01T00:00:00 and from midnight, with no zone | reference/parquet.md |
| PARQUET-3 | A float is stored as the binary64 value its derivation produced, never rounded | reference/parquet.md |
| PARQUET-4 | Parquet artifacts of one completed dataset read back identically, without identical bytes | reference/parquet.md |
| PARQUET-5 | A parquet source is one Parquet file, read in its stored field and record order | reference/parquet.md |
| PARQUET-6 | Every Parquet field has a non-empty unique name and a scalar type | reference/parquet.md |
| PARQUET-7 | The embedded Parquet type supplies the field type through a closed mapping that inverts the write mapping and admits signed integers, single-precision floats and other timestamp and time units | reference/parquet.md |
| PARQUET-8 | A Parquet null is the missing value, and present values arrive unchanged | reference/parquet.md |
| PARQUET-9 | A stored date, timestamp or time names an in-range civil value on a whole second | reference/parquet.md |
| PARQUET-10 | File metadata and layout never change the fields, records, types or values delivered | reference/parquet.md |
| SAS-1 | .sas7bdat and .xpt select the read-only SAS dataset and Transport profiles |
reference/sas.md |
| SAS-2 | A SAS input uses its stored encoding, and a Transport input declares its encoding | reference/sas.md |
| SAS-3 | Character storage supplies str and numeric storage float, and types may only narrow a numeric field |
reference/sas.md |
| SAS-4 | Numeric narrowing accepts only an exact integral value, and SAS dates count from 1960 | reference/sas.md |
| SAS-5 | SAS missing values become missing, and character values lose only trailing padding | reference/sas.md |
| SAS-6 | A SAS reader decodes only the captured snapshot, in stored field and record order | reference/sas.md |
| SAS-7 | A SAS or Transport file that cannot be decoded fails ingestion with one closed cause | reference/sas.md |
| SAS-8 | A SAS dataset yields only its live records, in stored order | reference/sas.md |
| ODM-1 | An .xml input is read as an ODM snapshot, refusing transactional content and skipping audit records |
reference/odm.md |
| DSJSON-1 | .json and .ndjson select the read-only Dataset-JSON 1.1 profiles, and the file alone is the source |
reference/dataset-json.md |
| DSJSON-2 | Each column's dataType supplies its field's type through a closed table, and types may only narrow it |
reference/dataset-json.md |
| DSJSON-3 | Each value is spelled as its column's dataType writes it and parses into its field's type, or fails ingestion |
reference/dataset-json.md |
| DSJSON-4 | Fields are the columns in order and records the rows in stored order, and records counts them |
reference/dataset-json.md |
| DSJSON-5 | A Dataset-JSON file that cannot be read fails ingestion with one closed cause | reference/dataset-json.md |
| SCHEMA-1 | A schema bundle is one entry point and every document it includes, loaded whole | reference/schema-language.md |
| SCHEMA-2 | A yamaa file declares its type and the oldest language version it needs, and an older engine refuses it | reference/schema-language.md |
| SCHEMA-3 | Documents reject duplicate keys, aliases, merge keys, explicit tags and unknown constructs | reference/schema-language.md |
| SCHEMA-4 | Scalars resolve under the YAML 1.2 core schema, where only true and false spellings are Boolean | reference/schema-language.md |
| SCHEMA-5 | A named type is a class, a value descriptor or a registry-backed type | reference/schema-language.md |
| SCHEMA-6 | Class fields are closed, and fields_from copies another class's fields unchanged |
reference/schema-language.md |
| SCHEMA-7 | A registry maps keywords to payload shapes, and a registry value names exactly one keyword | reference/schema-language.md |
| SCHEMA-8 | Two things in one naming list never share a name | reference/schema-language.md |
| SCHEMA-9 | A type expression is a type name, a list or dict of type expressions, or a union | reference/schema-language.md |
| SCHEMA-10 | One union shape is shorthand, expanded to its canonical class while validating | reference/schema-language.md |
| SCHEMA-15 | A written long form that holds only what its shorthand fills means the shorthand, and the lint reports it | reference/schema-language.md |
| SCHEMA-11 | A descriptor uses only the closed descriptor keywords, each where it applies | reference/schema-language.md |
| SCHEMA-12 | A value satisfies its type and every constraint its descriptor declares | reference/schema-language.md |
| SCHEMA-13 | A class value carries every required field and no undeclared field | reference/schema-language.md |
| SCHEMA-14 | A descriptor written in flow form and in block form is the same descriptor | reference/schema-language.md |
| SUB-1 | Submission metadata is optional and is declared only for columns the artifact carries | profiles/submission.md |
| SUB-2 | The free-form metadata map is never read and never carries a governed field name |
profiles/submission.md |
| SUB-3 | A specification declares its model, and the implementation guide a document binds it to must belong to that model | profiles/submission.md |
| SUB-4 | Dataset metadata states its label, observation class, record structure and whether it repeats | profiles/submission.md |
| SUB-5 | A dataset's domain defaults to the specification's domain and is declared only for SDTM and SEND | profiles/submission.md |
| SUB-6 | A column's submission data type defaults from its column type and model, within the closed set that type admits | profiles/submission.md |
| SUB-7 | length and significant_digits are declared exactly where the submission data type needs them |
profiles/submission.md |
| SUB-8 | A str column's length is a bound its completed values must meet, stated once |
profiles/submission.md |
| SUB-26 | A str column's date or time data type is an ISO 8601 form its completed values must have |
profiles/submission.md |
| SUB-9 | display_format and role describe a column for a reader and never change a value |
profiles/submission.md |
| SUB-10 | core takes its model's designations, and mandatory comes from the keys, the declaration, or the class and core |
profiles/submission.md |
| SUB-11 | A mandatory column is checked for missing values, and a not_missing beside it is redundant |
profiles/submission.md |
| SUB-12 | A column's value_level entries give the rows their where clause selects their own metadata |
profiles/submission.md |
| SUB-13 | Each row matches at most one entry of a column, an entry that matches no row warns, and an entry's origin is refuted on the rows it selects | profiles/submission.md |
| SUB-14 | Every column with submission metadata declares an origin from closed type and source vocabularies | profiles/submission.md |
| SUB-15 | Each model admits its own origin type and source pairs | profiles/submission.md |
| SUB-16 | A Predecessor, Other or Not Available origin carries a description | profiles/submission.md |
| SUB-17 | A value collected from a person references the annotated case report form, with a page under Submission |
profiles/submission.md |
| SUB-18 | A Derived origin declares its method | profiles/submission.md |
| SUB-19 | A declared origin the column's derivation contradicts is rejected, and an origin is never inferred | profiles/submission.md |
| SUB-20 | A Predecessor column is a bare copy of the column its description names | profiles/submission.md |
| SUB-21 | A method states its algorithm in prose and may add a name, a kind, code and documents | profiles/submission.md |
| SUB-22 | Comments and document references are declared where they are used and name declared documents | profiles/submission.md |
| SUB-23 | Rules needing no project file are checked on the specification alone, and the rest when a document composes it | profiles/submission.md |
| SUB-24 | With a transport, a character column is as long as the longest value the section's datasets carry | profiles/submission.md |
| SUB-28 | With a transport, a column or value-level definition that holds no value in its dataset has no data | profiles/submission.md |
| SUB-25 | Under ADaM a date, datetime or time is submitted as a SAS numeric date with a fixed display format and length |
profiles/submission.md |
| SUB-27 | An SDTM or SEND dataset carries its dates and times as text, never in a datetime or time column |
profiles/submission.md |
| CT-1 | A project's codelists compose by id across its sources, and a column binds one by id |
profiles/terminology.md |
| CT-2 | A codelist source's standard names its published terminology, and a source without one is sponsor-defined |
profiles/terminology.md |
| CT-12 | A codelist's format_name begins with $ exactly when the codelist is text |
profiles/terminology.md |
| CT-3 | A codelist lists its items or defers to an external dictionary, never both and never neither | profiles/terminology.md |
| CT-4 | Coded values are unique within a codelist, of its data type, and keep their declared order | profiles/terminology.md |
| CT-5 | decode and rank are declared for every item of a codelist or for none |
profiles/terminology.md |
| CT-6 | Only an extensible published codelist may carry sponsor-extended items, and an extended item declares no alias | profiles/terminology.md |
| CT-13 | A project binding needs a project file, and a specification checked or run without one fails validation | profiles/terminology.md |
| CT-7 | A bound codelist that lists items is the column's value set, and an external dictionary enforces nothing | profiles/terminology.md |
| CT-8 | A bound column's declared type admits its codelist's data type | profiles/terminology.md |
| CT-9 | An allowed_values verification beside a column's codelist of items is redundant |
profiles/terminology.md |
| CT-10 | A generated document carries exactly the codelists its output columns bind | profiles/terminology.md |
| CT-11 | An inventory-vocabulary column holds only names of datasets any submission section of the project declares | profiles/terminology.md |
| DEFINE-1 | A Define-XML document is composed from one selected submission section of the project file | profiles/define-xml.md |
| DEFINE-2 | The section's define target names the document's file, ends in .xml, and is define.xml beside a transport |
profiles/define-xml.md |
| DEFINE-3 | Two generations with the same captured inputs and creation time produce the same bytes | profiles/define-xml.md |
| DEFINE-4 | A Submission context adds the requirements a regulator imposes, and Other relaxes nothing else |
profiles/define-xml.md |
| DEFINE-5 | Each specs entry contributes one dataset, identified by its domain and placed in entry order |
profiles/define-xml.md |
| DEFINE-6 | The section's implementation guides belong to its model, and each dataset is bound to the one it selects | profiles/define-xml.md |
| DEFINE-7 | Every composed specification declares dataset and column submission metadata and column labels | profiles/define-xml.md |
| DEFINE-8 | Composition resolves the codelist, standard and document names a specification leaves unresolved | profiles/define-xml.md |
| DEFINE-9 | Every generated identifier is a fixed prefix and the declared identifiers of the object's position | profiles/define-xml.md |
| DEFINE-10 | Declared identifiers are unique in their space, so generated identifiers cannot collide | profiles/define-xml.md |
| DEFINE-11 | The document has one fixed element structure in a fixed order, and omits an element without content | profiles/define-xml.md |
| DEFINE-12 | ODM, Study and MetaDataVersion carry fixed attributes from the study and the selected section |
profiles/define-xml.md |
| DEFINE-13 | Each standard and supporting document produces its definition and its leaf | profiles/define-xml.md |
| DEFINE-14 | At most one annotated case report form is declared, and a value collected from a person requires one | profiles/define-xml.md |
| DEFINE-15 | Each dataset produces one ItemGroupDef, whose Purpose follows from its model |
profiles/define-xml.md |
| DEFINE-16 | A dataset's leaf names its transport file or its artifact, relative to the document and inside its directory | profiles/define-xml.md |
| DEFINE-17 | A dataset declared to have no data carries a comment that says why | profiles/define-xml.md |
| DEFINE-18 | Each output column produces one numbered ItemRef, keyed by its position in keys |
profiles/define-xml.md |
| DEFINE-19 | Each column produces one base ItemDef carrying one def:Origin per declared origin |
profiles/define-xml.md |
| DEFINE-20 | Each codelist produces one CodeList, whose item elements follow from whether its items declare decodes |
profiles/define-xml.md |
| DEFINE-21 | Methods and comments produce MethodDef and def:CommentDef elements, and all translated text carries one language |
profiles/define-xml.md |
| DEFINE-22 | Transport names are written only when they match the SAS transport name patterns | profiles/define-xml.md |
| DEFINE-23 | The document's bytes are fixed: UTF-8, one element per line, two-space indentation and fixed escapes | profiles/define-xml.md |
| DEFINE-24 | Generated text never carries a carriage return or tab, nor a line feed in an attribute value | profiles/define-xml.md |
| DEFINE-25 | A complete document, valid against the selected Define-XML schema, is published atomically or not at all | profiles/define-xml.md |
| DEFINE-26 | Constructs outside the profile cannot be declared and are never generated | profiles/define-xml.md |
| DEFINE-27 | A column's value-level entries generate one value list, and a where clause and a definition per entry | profiles/define-xml.md |
| DEFINE-28 | Define-XML requires the project's study and the section's standards and define, which a run does not |
profiles/define-xml.md |
| DEFINE-29 | A section selects its Define-XML release explicitly, retaining 2.1.11 when omitted | profiles/define-xml.md |
| DEFINE-30 | Historical metadata is a literal record and makes no assertion about current derivations or data | profiles/define-xml.md |
| JSON-1 | A section's transport requests one transport file per composed dataset, named for the dataset beside the document |
profiles/dataset-json.md |
| JSON-2 | Every transport file has exactly one writer | profiles/dataset-json.md |
| JSON-3 | A dataset declared to have no data has no transport file, and a dataset without rows declares it | profiles/dataset-json.md |
| JSON-4 | The file is Dataset-JSON 1.1 in the representation transport selects and valid against that standard's schema |
profiles/dataset-json.md |
| JSON-5 | The rows are the published artifact's rows, read the way a consumer reads a producer's artifact, and no display precision reaches them | profiles/dataset-json.md |
| JSON-6 | Every metadata member comes from the declarations the Define-XML document is generated from | profiles/dataset-json.md |
| JSON-7 | The file carries the standard's members in a fixed order, omitting absent ones: one object, or a first line and one row per line | profiles/dataset-json.md |
| JSON-8 | metaDataRef names the Define-XML document beside the file |
profiles/dataset-json.md |
| JSON-9 | Each output column produces one column object carrying that column's Define-XML metadata | profiles/dataset-json.md |
| JSON-10 | dataType maps the resolved submission data type through a closed table, and an ADaM date, datetime or time targets an integer |
profiles/dataset-json.md |
| JSON-11 | Each row is an array of its values written by column type, with missing as null |
profiles/dataset-json.md |
| JSON-12 | When Dataset-JSON is requested, each dataset's leaf names its Dataset-JSON file | profiles/dataset-json.md |
| JSON-13 | The file's bytes are fixed: UTF-8, one layout per representation, one spelling per string and number | profiles/dataset-json.md |
| JSON-14 | Transport files are published before the document, and only after every file renders and validates | profiles/dataset-json.md |
| JSON-15 | A file this profile writes reads back through the Dataset-JSON source profiles as its published table | profiles/dataset-json.md |
| XPT-1 | A section's transport: xpt writes each composed dataset as one SAS Transport version 5 file |
profiles/xpt.md |
| XPT-2 | The file is a fixed sequence of 80-byte records in the transport layout | profiles/xpt.md |
| XPT-3 | The header records carry fixed text, the dataset's name and label, and the creation time | profiles/xpt.md |
| XPT-4 | Each output column produces one NAMESTR, in output.columns order |
profiles/xpt.md |
| XPT-5 | Names are names DEFINE-22 admits, and labels are at most 40 printable ASCII characters | profiles/xpt.md |
| XPT-6 | A str column is a character variable, a number a numeric one, and a date travels as its model submits it |
profiles/xpt.md |
| XPT-7 | A character value is printable ASCII of at most 200 bytes without a trailing blank, and missing is blanks | profiles/xpt.md |
| XPT-8 | A numeric value is an IBM System/360 double converted exactly from binary64, and missing is a period | profiles/xpt.md |
| XPT-9 | A numeric variable carries a display format only when its declared one parses as a SAS format | profiles/xpt.md |
| XPT-10 | A file above 5,000,000,000 bytes, or one ending in an all-blank observation, is refused before writing | profiles/xpt.md |
| FUNC-1 | Project functions come only from the function files the caller's project lists, through the running host's implementation | profiles/functions.md |
| FUNC-2 | A function file is admitted on its own against the function schema before any activation or study read | profiles/functions.md |
| FUNC-3 | One host language applies to every function, and a declared lock pins the called packages | profiles/functions.md |
| FUNC-4 | Each logical function has one closed definition, and a call names only the function and its arguments | profiles/functions.md |
| FUNC-5 | A signature is closed and named, and every argument and default matches its declared type exactly | profiles/functions.md |
| FUNC-6 | A call argument is one leaf of the expression grammar, never a composed expression | profiles/functions.md |
| FUNC-7 | An omitted optional argument takes its default, and a missing argument short-circuits unless its parameter accepts missing | profiles/functions.md |
| FUNC-8 | A binding is a statically named installed callable, invoked once for each logical row | profiles/functions.md |
| FUNC-9 | A binding returns one scalar of its declared type, and missing only when its definition permits it | profiles/functions.md |
| FUNC-10 | An invocation failure identifies the logical function, its callable and its authored source | profiles/functions.md |
| FUNC-11 | Each definition's inline tests cover every obligation its contract implies | profiles/functions.md |
| FUNC-12 | Every build runs every case of every called function before any study data is read | profiles/functions.md |
| FUNC-13 | A numeric result is compared at comparison_decimals with the one rounding, and is never changed |
profiles/functions.md |
| PROJECT-1 | A project file is passed explicitly and names one study's functions, host locks, terminology and submission sections | profiles/project.md |
| PROJECT-16 | A project file names at most one parent, and composes on it section by section |
profiles/project.md |
| PROJECT-2 | environments holds each host language's lock, and each host reads only its own |
profiles/project.md |
| PROJECT-3 | A section needs only specs, and the study metadata a run does not read is required only by Define-XML |
profiles/project.md |
| PROJECT-4 | A project file's relative paths resolve from the project file that writes them | profiles/project.md |
| PROJECT-5 | A listed specification's name is its domain, unique across the project |
profiles/project.md |
| PROJECT-6 | Selecting a project specification by name accepts only a name the project defines | profiles/project.md |
| PROJECT-14 | Selecting a project section accepts only a section the project declares | profiles/project.md |
| PROJECT-7 | Checking a project checks every listed specification in section and listing order, with the project findings | profiles/project.md |
| PROJECT-8 | A project run builds each specification of its run scope once, a linked producer before its consumers | profiles/project.md |
| PROJECT-9 | A producer outside the run scope is not built, and its consumer reads the saved file | profiles/project.md |
| PROJECT-10 | An input that reads a run-scope artifact without a schema link fails |
profiles/project.md |
| PROJECT-11 | A failed run-scope specification stops only the specifications that depend on it | profiles/project.md |
| PROJECT-12 | Saving a project run validates every target first, then publishes specification by specification in run order | profiles/project.md |
| PROJECT-13 | A project submission composes each selected section's Define-XML document in section order | profiles/project.md |
| PROJECT-15 | A project submission composes a specification that declares a run report only with the artifact and inputs that report records | profiles/project.md |