Types and Values
One type system covers every typed position in the format. A Workfile’s inputs, a state’s accepts, an agent step’s returns, and every field declaration in a manifest or an overlay use the type expressions below. The expression language operates on values of these types.
Type expressions
Section titled “Type expressions”The type expressions are string, int, float, bool, timestamp, duration, file, json, enum[...], list[T], map[string, T], and object types expressed as JSON Schema. The grammar states their form. The serialization rules require that a type expression is always quoted.
Object types use JSON Schema draft 2020-12. A $ref MUST be a local pointer into the same document, of the form #/schemas/<name>. Implementations MUST reject an external reference.
file is a reference to content in blob storage, with a content type and a size. Implementations MUST NOT embed file contents in run state.
Expressions operate on run state, so no expression can compute over a file’s contents. A checksum, a text extraction, or a format conversion is always a connector action, never a filter chain. The canonical data connector holds content operations that belong to no one system.
Representation and comparison
Section titled “Representation and comparison”Integers. An int is a signed 64-bit integer, and arithmetic on it is exact. A result outside the representable range is an evaluation fault.
Floats. A float is an IEEE 754 binary64 value. NaN, positive infinity, and negative infinity are not values of this format. An operation that would produce one of them is an evaluation fault.
Numeric operators. +, -, *, /, and % accept numbers only. An operation with one int operand and one float operand converts the int to float and yields a float. / always yields a float. % accepts two int operands only, and its result takes the sign of the dividend. Division or modulo by zero is an evaluation fault. An operand outside an operator’s domain is an evaluation fault. Strings compose by interpolation, format, or join, and never by +.
Strings. A string is a sequence of Unicode code points. Implementations MUST NOT normalize a string value on parse, on binding, or on comparison. Equality and ordering compare code point sequences. Note: two strings that Unicode considers canonically equivalent can compare unequal. The case filters use Unicode simple case mapping and are independent of locale.
Timestamps. A timestamp holds an instant with millisecond precision and a display zone. A literal is an RFC 3339 date-time with a mandatory time offset. Implementations MUST reject a second value of 60. Equality and ordering compare the instant alone, so two timestamps that name one instant in different zones are equal. to_timezone changes the display zone only. format_time is the only filter that reads the display zone. A zone is named by an IANA Time Zone Database identifier, or by a fixed offset. Implementations MUST record the time zone database version in the resolution of every run.
Durations. A duration is a signed count of milliseconds. The literal grammar takes one or more <integer><unit> components, with units ms, s, m, h, and d, in strictly descending order of unit, each unit at most once. 1h30m and 500ms are durations. A day is exactly 86400000 milliseconds, and has no calendar or daylight-saving meaning. A literal is never negative. diff can produce a negative duration.
Collections. A list is ordered. A map has string keys. Lists are equal when they have equal length and equal elements in order. Maps are equal when they have the same key set and equal values.
Files. A file is an opaque reference. Equality compares the reference. No ordering is defined.
Equality. == and != are total and never coerce. Values of different types are unequal, and null is equal only to null. int and float are both numbers, so 1 == 1.0 is true.
Ordering. <, <=, >, and >= are defined between two numbers, two strings, two timestamps, or two durations. Any other pairing, including an ordered comparison against null, is an evaluation fault. sort, sort_by, min, and max use this ordering, and a collection that mixes ordered types is an evaluation fault.
Booleans. There is no implicit truthiness. Every guard position requires a boolean: when, a choose arm, until, the condition of a conditional expression, the argument of keep, and the outcome of a reconcile. A guard of any other type is a validation error where the type is statically known, and an evaluation fault otherwise. not, and, and or accept booleans only.
Values typed json. A value whose type this standard cannot establish statically is typed json. A number in such a value that has no fraction and no exponent, and that fits the int range, is an int. Every other number is a float.