Skip to content

Generator reference ​

Every built-in generator type and its parameters, verified against crates/pgdl/src/generators/*.rs, compile.rs, and composition.rs. For the readable guide see Generators (PGDL); for a worked gallery see the generator gallery.

The envelope ​

The engine runs a uniform envelope — { use, params, constraints, modifiers } — but a PGDL definition is authored per-type and compiled to it. The two authoring forms:

json
{ "type": "logic", "algorithm": "int_between", "params": { "min": 1, "max": 9 } }
json
{ "use": "@phony/core:logic.int_between", "params": { "min": 1, "max": 9 } }

type maps to a built-in reference; use names any registered generator directly (the open-set escape hatch for custom/packaged generators). The PGDL type → reference mapping:

typeReferenceKeys gathered into params
logic@phony/core:logic.<algorithm>params (verbatim)
list@phony/core:listsource, values, key, where
model@phony/core:modelsource, generation
statistical@phony/core:statisticalmode, values, distribution, params, differential_privacy, variables, correlations
event_sequence@phony/core:event_sequenceevents

The template and linked types were folded into composition and now error with guidance (author a composition body/variants, or a list over an asset).

Modifiers ​

Cross-cutting filters applied to any generator's output, set as top-level keys on a PGDL definition.

ModifierTypeEffect
uniquebooleanEmit distinct values across rows. Re-rolls on a collision (up to 200 attempts) then errors if it cannot. Nulls are exempt (they neither enter the dedup set nor burn attempts).
nullableboolean or numberProbability of emitting null. true uses the default rate 0.1; a number is an explicit rate in [0, 1]. Drawn on a dedicated sub-stream so it never perturbs the value stream.
transformstring (PEL)A PEL expression applied to the produced value, with value bound to it.
json
{ "type": "logic", "algorithm": "int_between", "params": { "min": 1, "max": 1000 },
  "unique": true, "nullable": 0.05, "transform": "format(value, 'number')" }

Logic ​

Pure algorithms, no data source, locale-independent. One algorithm per definition, selected by algorithm. Every value is a pure function of the cell seed (and, for sequence, the row index).

algorithmOutputParameters (default)
uuid_v4string—
uuid_v7string— (synthetic, index-sortable timestamp = reference instant + index)
ulidstring— (26-char Crockford base32)
nanoidstringlength (21)
int_betweenintegermin (0), max (2147483647), except (array, none)
float_betweennumbermin (0), max (1), precision (2)
booleanbooleanprobability (0.5, clamped to [0,1])
datetime_betweenstringstart (1970-01-01), end (2038-01-01)
date_betweenstringstart (1970-01-01), end (2038-01-01)
time_betweenstringstart (00:00:00), end (23:59:59)
timestampintegerstart (1970-01-01), end (2038-01-01) — Unix seconds
sequenceintegerstart (1), step (1) → start + row·step
gaussiannumbermean (0), stddev (1) — rounded to 6 decimals
exponentialnumberlambda (1) — rounded to 6 decimals
digitsinteger or stringdigits (1, clamped 1–18), strict (false), leading_zero (false)

Notes:

  • int_between errors if min > max. except is a list of values to avoid; it errors if it excludes the whole range or cannot avoid the set within 1000 tries.
  • float_between errors if min > max.
  • datetime_between / date_between / timestamp bounds accept ISO-8601 or relative specs (now, today, -1year, now+7days); bounds are ordered so either direction works. time_between bounds are HH:MM:SS / HH:MM.
  • digits: the value spans [min, 10^digits − 1], where min is 10^(digits−1) when strict, else 0. leading_zero returns a zero-padded string; otherwise an integer.
json
{ "type": "logic", "algorithm": "digits", "params": { "digits": 4, "strict": true, "leading_zero": true } }

List ​

Select from a finite set (inline or an asset), optionally keyed or filtered. Selection is inverse-CDF weighted, so it follows weights exactly and reproducibly.

ParameterTypeDescription
valuesarrayInline candidate set.
sourcestring or objectAsset reference: a non-"inline" string name, or { "asset": name }. "inline" (or omitted) means use values.
keystringWhen the source is a map, pick from the source[key] bucket (must be an array).
wherestring (PEL)Predicate evaluated per element with item bound to the candidate (plus the caller's bindings). Keeps matching elements, then picks.

Element shapes:

  • a plain scalar — returned as-is;
  • { value, weight } — unwraps to value; weight defaults to 1, 0 means never selected (kept but excluded from the draw);
  • any other object (metadata record) — returned whole.

An empty selection (nothing matched), or all-zero weights, is an error. A missing key bucket is an error.

json
{ "type": "list", "source": "districts", "key": "{{ city }}",
  "where": "item.population > 100000" }

Model ​

Delegate to the trained N-gram engine. The model is an asset resolved by name. Output is a pure function of the cell seed. See the .ngram format.

ParameterTypeDescription
sourcestring (required)The model asset name.
generationobject{ mode, params }. mode defaults to word.

generation.mode and its params:

modeparams (default)Notes
word—Honours the top-level constraints.
sentenceword_count (learned), punctuation ("."; string or array to pick from), starts_with—
textmax_chars (200), suffix (""), starts_withProse up to max_chars.
paragraphsentence_count (learned), starts_with—
poemverses (4), stanza_length (4), max_words (8)—
acrosticinitials (""), max_words (8)An unsatisfiable initial errors (no silent fallback).
real_wordprefix (none)Samples an actual training item; null if none matches.

starts_with may come from generation.params or fall back to the top-level constraints.

Top-level constraints (applied where the mode supports them):

ConstraintTypeDescription
starts_withstringRequire a prefix.
ends_withstringRequire a suffix.
containsstringRequire a substring.
min_lengthintegerMinimum length.
max_lengthintegerMaximum length.
exclude_originalsboolean (false)Never emit a verbatim training item.
json
{ "type": "model", "source": "first_names",
  "generation": { "mode": "word" }, "constraints": { "min_length": 3, "starts_with": "M" } }

Statistical ​

Distribution-matching values. mode defaults to continuous.

modeOutputPurpose
categoricalanyFrequency-preserving weighted pick.
continuousnumberSample a named distribution.
multivariateobjectCorrelated draws.
algebraic—Not a generator mode: express it with a composition let/computed step (errors with that guidance).

categorical ​

ParameterTypeDescription
valuesarray (required)Elements { value, weight }; weight defaults to 1, 0 = never. All-zero (or empty) errors.

continuous ​

ParameterTypeDescription
distributionstring (normal)The distribution to sample.
paramsobjectDistribution parameters (below).
differential_privacyobjectOptional DP noise (below).

Constraints min / max (top-level constraints) form a window: the value is resampled up to 50 times to land inside it, then clamped. The result is rounded to 6 decimals.

Distributions and their params (defaults):

distributionParameters
normalmean (0), stddev (1)
lognormalmu (0), sigma (1)
exponentiallambda (1)
uniformmin (0), max (1)
poissonlambda (1)
betaalpha (1), beta (1)
gammashape (1), scale (1)

differential_privacy object:

KeyTypeDefaultDescription
enabledbooleanfalseTurn DP noise on.
epsilonnumber1.0Privacy budget (floored at 1e-6).
sensitivitynumber1.0Query sensitivity.
mechanismstringlaplacelaplace or gaussian.

DP noise is drawn on its own stream so it never disturbs the value stream.

multivariate ​

ParameterTypeDescription
variablesarray (required)Each { name, mean (0), stddev (1) }. Names must be non-empty and unique.
correlationsarrayAn N×N correlation matrix (default identity). Must be square and positive-definite.

Returns an object { name: value, … }, values rounded to 6 decimals, drawn jointly via a Cholesky factorization of the correlation matrix.

json
{ "type": "statistical", "mode": "continuous", "distribution": "lognormal",
  "params": { "mu": 3, "sigma": 0.5 }, "constraints": { "min": 0 } }

Event sequence ​

Chronologically valid date series. Returns an object mapping each event name to an ISO-8601 datetime, or null when an optional event is skipped or its predecessor was skipped.

ParameterTypeDescription
eventsarray (required, ≥1)The event definitions.

Each event object:

KeyTypeDescription
namestring (required)The event's key in the output.
basebooleanMarks an anchor event that lands in range.
rangeobject{ start, end } for a base/anchor event (ISO or relative specs).
afterstringName of the predecessor; this event is the predecessor plus a delay.
probabilitynumberGate in [0, 1]: below the roll, the event (and dependents) is skipped (null). Rolled on a dedicated sub-stream.
delayobject{ min, max } durations added to the predecessor.

Rules: the sequence needs an anchor (an event with base: true or with no after); an after must name a defined event (both checked statically). A delay duration is a number plus a unit — s (or empty), m, h, d, w (e.g. 1d, 24h, 2w).

json
{ "type": "event_sequence", "events": [
  { "name": "signup", "base": true, "range": { "start": "-1year", "end": "now" } },
  { "name": "first_purchase", "after": "signup", "probability": 0.6, "delay": { "min": "1d", "max": "30d" } }
] }

Composition ​

A generator authored as pure data (PGDL + PEL) — how a generator is made of other generators, nested without limit. Registered by name, then usable exactly like a built-in. Its params are validated against its own manifest on every call.

json
{
  "name": "@acme/finance:net",
  "version": "0.1.0",
  "description": "Net amount after tax.",
  "params": { "rate": { "type": "number", "default": 0.18 } },
  "let": {
    "subtotal": { "type": "logic", "algorithm": "float_between", "params": { "min": 10, "max": 500 } },
    "tax":      { "computed": "round(subtotal * rate, 2)" }
  },
  "body": "{{ subtotal + tax }}"
}
FieldTypeDescription
namestring (required)Namespaced generator name.
versionstring (0.1.0)Manifest version.
descriptionstringManifest summary.
paramsobjectInput params: each { type, required (false), default }.
letobjectNamed steps, evaluated in dependency order (topologically sorted; a cycle errors).
body / variants / output—Exactly one output form (below).

Everything a composition references resolves against its own local bindings (its params + let results) — never a table, row, or sibling field. Every reference is checked at registration against the known param/let names (a where predicate may also use item); a typo fails then, not at run time.

let step forms ​

FormShapeResult
Generatorany generator definition ({ type … } or { use … })The sub-generator's value. Its string params are PEL templates evaluated against the locals, so parent values thread through.
Computed{ "computed": "<PEL expression>" }The expression's value (bare expression over prior locals).
Repeat{ "repeat": { count, of, unique? } }An array of count sub-generator outputs.

The repeat step (the "N items per parent" primitive):

KeyTypeDescription
countinteger, "a-b" range string, or PEL expression stringHow many items. A range draws one integer per invocation; an expression resolves over the locals (floored to an integer).
ofgenerator definitionThe item generator; its params are interpolated against the locals so items can reference the parent.
uniqueboolean (false)De-duplicate items, with up to 200 retries each; failing to fill errors.

Output forms ​

FieldTypeOutput kind
bodytemplate stringstring (the rendered template)
variantsarray of { pattern, weight? }string — a weighted choice among body templates. weight defaults to 1, 0 = never; empty or all-zero errors.
outputstructured JSONobject / array / any — string leaves are evaluated against the locals (a whole-expression leaf keeps its native type).
json
{
  "name": "@acme/orders:order",
  "let": {
    "id":    { "type": "logic", "algorithm": "uuid_v4" },
    "lines": { "repeat": { "count": "1-5", "of": { "type": "logic", "algorithm": "int_between", "params": { "min": 1, "max": 9 } } } }
  },
  "output": { "order_id": "{{ id }}", "quantities": "{{ lines }}" }
}

Phony Cloud — Documentation & Specification