Results schema
The shape of a cfdl run results document. This is the published contract,
also served at cfdl.dev/schemas; every committed results golden is validated
against it by make results-schema.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://cfdl.dev/schemas/CFDL_v0_1_Results.schema.json",
"title": "CFDL v0.1 Results",
"type": "object",
"additionalProperties": false,
"required": [
"results_version",
"model_hash",
"engine",
"warnings",
"deterministic",
"scenarios",
"monte_carlo",
"ledger_hash",
"run"
],
"properties": {
"results_version": {
"type": "string",
"const": "0.17",
"description": "Schema version of this document. 0.17 publishes the trace (`deterministic.trace`, and each scenario's): for every lifecycle, event, option, stream and field, why each period is what it is, as runs of one reason — a lifecycle's evaluation each period, with the guards it tested and what each read, whether the entity moved or held; an event's and an option's test; a stream's reason for its cell; a field's source — and refers to the journal entry that caused a reason by its position. 0.17 also journals an event's firing as a `fire` entry whose children are its actions, an option's exercise with its payoff `amount`, the `entity` it is credited to and its actions as children, and the values a firing's or a transition's condition read as `reads`; marks every stream and option series with `cash`; attributes an option's payoff series to its `entity`; adds `trace` to the Monte Carlo section, summarizing each actor's reasons across the trials; covers the trace in `ledger_hash`; removes the `activate_contract` and `deactivate_contract` journal actions, which the language withdrew and nothing emitted; publishes `run`, the run configuration as the run used it; gives each scenario summary and the Monte Carlo section their own `ledger_hash`; and leaves out the model's `source` on a review page row the run configuration overrides. 0.16 publishes each scenario whole — its series, annual rollup, journal, transitions, slices, review page and, where enriched, statements and domain metrics — beside its metrics, so a scenario grid has per-period columns and two runs can be compared. 0.16 also publishes a ratio row's `numerator` and `denominator` beside its values, so a regrouped column divides their sums. 0.16 also withdraws `model.moic` — a multiple partitions cash by kind, which the engine cannot know at the model level; a model states its own through `moic(party.<p>)`, a slice's `moic` or a declared metric — and adds `omitted` to a scenario summary and a trial summary: the declared metrics that run could not evaluate, each with the reason, left out of `metrics` rather than published as a number; the deterministic run still refuses. 0.16 also publishes, in `graph`, each contract's `term`, `currency` and `terms` and each entity's `fields`: every stated term or field as the run resolved it, with the type and unit its pack declares, so a table over the graph — a rent roll, a tranche table — reads the agreement beside its cash without a statement (docs/01 §15.5). 0.16 also publishes the master machine's state as `master` on a refined machine's transitions. 0.16 also marks a transition that re-entered a state by history with `resumed`, naming that state. 0.15 replaces `inputs.resolved` with `inputs.assumptions`, the review page: one row per assumption, a set's fields each on their own row, with its shape, type, unit, value, origin and source. 0.14 removes the `ignored` journal outcome — an action kind the engine does not execute refuses the run — and publishes `model.npv` and `run.annual_discount_rate` only when a discount rate was stated. 0.13 publishes the model's contracts in `graph.contracts` — each with its type, master, instance, subject, parties and the streams lowered from it — and attributes each lowered stream series to its contract and its line by role (`contract` and `line` on the series); a slice's selection records its `lines`. 0.12 separates the model from its views: `model_hash` covers the IR without `views` (slices and statements), and `ledger_hash` now covers the journal and transitions beside the series. 0.11 adds model-declared statements: `pack` on the statements section is optional, and a statement may carry `metrics`. 0.10 adds `window` to a slice's selection — a reporting bound whose periods are the only ones the slice folds. 0.9 carries every metric a Monte Carlo trial computed into its trial summary, summarizes each of them across the trials with the full set of percentiles, and adds `trials` to a metric summary — the count of trials that published that name. 0.8 adds `slices` — declared partial selections with their matched streams, net series and figures, and no reconciliation block by design. 0.7 publishes the model's entity graph (`graph`) and attributes each stream series to its owning entity and category. 0.6 nests an act's own acts under it as `children`. 0.5 added the machine's `transition` journal action. 0.4 added the account journal actions. 0.3 added `ledger_hash`, the optional `inputs` section, and `category` on IR streams."
},
"model_hash": {
"type": "string",
"description": "Identifies the MODEL: a hash of the compiled IR without its `views` and without where anything is written. A slice filters and a statement organizes, and neither produces cash, so two users who look at identical results differently are running the same model and share this hash. The IR's source positions — each declaration's file and span, the files the model is written in, a warning's location — are left out too, every expression is in its canonical spelling, and every number is read by its value (`0.0` and `0` are one number), so a comment, a blank line, spacing inside an expression, a declaration moved to another file or a host that re-encodes the IR's numbers leaves this hash where it was. A declared metric is NOT excluded — it is a figure the model claims.",
"minLength": 8
},
"ledger_hash": {
"type": "string",
"description": "Identifies the RESULT: SHA-256 over the canonical form of the ledger — `deterministic.series` and `annual_rollup`, plus the journal and the transitions, because a ledger has journal entries in it and the trace of what the model did belongs to what came out. It covers the LEDGER, not the metrics: NPV and IRR are derived FROM the ledger, so including them would make the hash move for a reason the ledger did not, and `domain.*` folds are excluded on the same argument. It is invariant to the discount rate, which is correct — the ledger is cash before discounting. The RUN CONFIGURATION is deliberately not hashed here: folding it in would give three prepayment speeds over one model three different hashes, with no way to tell whether the cash moved or only a setting, and comparing results across runs is the point."
},
"engine": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"version": {
"type": "string",
"minLength": 1
},
"build": {
"type": "string"
}
}
},
"warnings": {
"type": "array",
"items": {
"type": "string"
},
"description": "Run-level warnings, `CODE: message`: the compile's kept warnings first (a pack convention questioned, carried in the IR), then the engine's own. A warned run is a suspect run to the benchmark harness."
},
"run": {
"type": "object",
"description": "The run configuration as the run used it: the run configuration document with each inputs file's content in place of its path, and the discount rate, as-of date or trial range a caller filled in where the document is silent. Published, not hashed: it is what the run was asked, and `ledger_hash` is what came out. A package's verifier checks it against the package's run configuration and inputs files. A run configured in code publishes what its fields state.",
"additionalProperties": true
},
"inputs": {
"$ref": "#/$defs/InputsSection"
},
"deterministic": {
"$ref": "#/$defs/DeterministicSection"
},
"scenarios": {
"$ref": "#/$defs/ScenariosSection"
},
"monte_carlo": {
"$ref": "#/$defs/MonteCarloSection"
},
"domain_metrics": {
"$ref": "#/$defs/DomainMetrics"
},
"statements": {
"$ref": "#/$defs/StatementsSection"
},
"graph": {
"$ref": "#/$defs/ResultsGraph"
},
"slices": {
"type": "array",
"items": {
"$ref": "#/$defs/SliceResult"
}
},
"shard": {
"$ref": "#/$defs/ShardRecord"
},
"shards": {
"type": "array",
"description": "On a document merged from entity shards: one row per shard, in the order merged, with its model and ledger hashes and the entities it holds, so a merged series traces to the run that produced each part.",
"items": {
"$ref": "#/$defs/ShardSummary"
}
}
},
"$defs": {
"Currency": {
"type": "string",
"pattern": "^[A-Z]{3}$"
},
"Decimal": {
"type": "number"
},
"Money": {
"type": "object",
"additionalProperties": false,
"required": [
"amount",
"currency"
],
"properties": {
"amount": {
"$ref": "#/$defs/Decimal"
},
"currency": {
"$ref": "#/$defs/Currency"
}
}
},
"Date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"SeriesIndex": {
"type": "object",
"additionalProperties": false,
"required": [
"calendar",
"start",
"periods"
],
"properties": {
"calendar": {
"type": "string",
"enum": [
"daily",
"monthly",
"quarterly",
"annual"
]
},
"start": {
"$ref": "#/$defs/Date"
},
"periods": {
"type": "integer",
"minimum": 1
}
}
},
"Scalar": {
"description": "Scalar metric output",
"oneOf": [
{
"type": "number"
},
{
"$ref": "#/$defs/Money"
},
{
"type": "string"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
},
"Series": {
"description": "Time series aligned to the model timeline",
"type": "object",
"additionalProperties": false,
"required": [
"index",
"values"
],
"properties": {
"index": {
"$ref": "#/$defs/SeriesIndex"
},
"offset": {
"description": "Where in each period this series' cash falls: 0.0 at the period's open (an annuity due, or a one-shot on its date), 1.0 at its close (an ordinary annuity, the default), 0.5 for the mid-period convention. The same offset used to discount the series, and the axis `model.wal_years` and `model.payback_years` are measured on — so an ordinary annuity's first monthly collection is at 1/12 of a year, not 0. A waterfall step's series carries its waterfall's schedule placement — `on day 25` puts every step on the 25th. Absent on aggregates (`model.net_cash_flow`, the annual rollup), which sum streams whose placements differ. See 12_payment_timing.md. Absent on field series, which are not paid and so sit nowhere in their period.",
"type": "number"
},
"entity": {
"type": "string",
"description": "The entity this series is attached to (`asset.tower`, `container.fund`). Present on stream series, on an option's payoff series, on a waterfall step's series and on its shortfall series; a subtotal spans owners and an aggregate has none. A stream's entity is its owner. A waterfall step's is whoever the step pays: the party it names, the owner of the account it pays into (`party.holders` for an account that party owns), or the account's own name when the structure owns it. The entity that hosts the waterfall has earned the cash it distributes, so its `entity.<symbol>.net_cash_flow` is that cash before the split, and a payee's is what it receives; the series attributed to an entity are the parts of its `net_cash_flow` apart from a non-cash stream (`cash: false`), which that figure leaves out. With `graph`, this is what lets a consumer attribute cash to a thing without the IR: name inspection is not a substitute, because a pack-lowered stream's name does not contain its owner's symbol. An option's payoff series carries the entity the option is written on, which the rollup credits."
},
"category": {
"type": "string",
"description": "The stream's declared category (`operating.revenue.base_rent`). Present on categorized stream series and on an option's payoff series when the option states a category. Ownership says whose cash; category says what kind — the two axes a selection needs."
},
"contract": {
"type": "string",
"description": "The contract this stream was lowered from (`cre.lease_unit.tenant_a`). Present on pack-lowered stream series only. With `graph.contracts`, the third axis beside `entity` and `category`: whose cash, what kind, and under which agreement."
},
"line": {
"type": "string",
"description": "The line this stream is, by the role its contract's master names (`interest`, `rent`, `proceeds`). Present on pack-lowered stream series only. With `contract`, what lets a consumer fold every debt's interest without knowing any pack's category spelling."
},
"moves": {
"type": "string",
"description": "The account this stream moves (`asset.tower.balance.senior`). Present on a stream that moves one. What lets a consumer roll an account's schedule from results alone: a loan's payoff is often made by another contract, a sale or a take-out, and only the account it moves says whose balance it retires."
},
"cash": {
"type": "boolean",
"description": "Whether the rollup sums this series into the model's and its owner's cash. Present on every stream's and every option's series: `false` is a non-cash stream, an accrual or a measure, which publishes under its own name and never enters a total."
},
"values": {
"type": "array",
"minItems": 1,
"items": {
"oneOf": [
{
"$ref": "#/$defs/Decimal"
},
{
"$ref": "#/$defs/Money"
},
{
"type": "null"
}
]
},
"description": "One entry per period. Money for a cash series; a bare number for a dimensionless one such as an entity field, which has no denomination."
}
}
},
"MetricMap": {
"type": "object",
"description": "Named metric scalars. The prefix says who minted the number: `model.*` is the engine's (total, npv, irr, payback, wal; there is no whole-model multiple, since a multiple partitions cash by kind, which only a party's account, a slice or a declared metric can state), `domain.<pack>.*` is the active pack's, and `metric.<name>` is one the MODEL declared (`docs/01` §15.3) — a figure this deal solved for, evaluated once at the horizon over the finished projection; it is `null` when its fold has no answer, such as a maximum over nothing or a mean over periods that were all undefined. `stream.<name>.total` is a stream's own sum. `run.*` records what the run was asked: `run.annual_discount_rate` or `run.annual_discount_curve` (the curve's name) for what it discounted with, `run.periods_per_year`, and `run.as_of` when one was stated. A declared metric appears in every scenario summary as well, since scenarios and the deterministic block publish the same map. `model.irr`, `model.payback_years` and `model.wal_years` exist only where cash moved: a cell at or below 1e-9 in magnitude — a signed zero, a flow cancelled to the last digit — is not an observation for any sign-based fold, so a series of such cells publishes none of them. `model.irr` is also omitted, with a run warning, where the only rate that solves the flows is -100% a year: flows whose net never returns what they invest can still alternate in sign inside each period, and they solve only at the floor of the rate search, which is not a return. `model.irr` is always solved on the MODEL's grain, whatever `valuation_grain` the run states: it is a property of the cash flows, not of the convention chosen for reporting a present value. `model.npv` does follow the grain, so under `valuation_grain: \"annual\"` the two are struck on different conventions and discounting the annual buckets at the reported IRR will not give zero. Measured on the CRE benchmarks the gap is small where it is measurable at all — 6.5696% against 6.5540% on the one case whose flows have a single well-defined root.",
"additionalProperties": {
"$ref": "#/$defs/Scalar"
}
},
"SeriesMap": {
"type": "object",
"description": "Named time series outputs. Keys are prefixed by what they are: `stream.<name>` and `option.<name>` are cash and carry a currency; `model.net_cash_flow` is their aggregate; `<family>.<entity>.<field>` is an entity field and is NOT cash — it is a bare number with no currency and no offset, published so a recurrence can be inspected, and it never enters model.total, model.npv, the annual rollup or any domain metric. `entity.<symbol>.net_cash_flow` is an entity's cash AGGREGATED BY RELATION — its own streams plus every descendant's, following `part_of` rather than a name prefix, so a building's cash is its units' cash because they ARE its units. An entity with no children carries its own streams only, which is the pool that models collective behavior directly; the grain is the modeler's choice. Like a subtotal it is a fold OF the cash and never counts AS cash — excluded from model.total, model.npv, model.net_cash_flow and the annual rollup, because counting a parent and its children would double what it touches. `metric.<contract>.<figure>` is a pack valuation's figure published every period (`docs/07` §6.4): the appraisal at each period of the cash horizon over the finished projection, a bare number or `null`; like a field it is never cash and no stream pays it. `shortfall.<waterfall>.<step>` is what a waterfall step was owed less what it took, per period (`docs/01` §10.5): a bare number, zero where the step was paid in full or the waterfall did not run, carrying the step's entity and, where the step names them, its contract and line. It is the absence of cash and never cash: it enters no total, no net cash flow, no category fold and no valuation. `domain.<pack>.<name>` is a per-period SUBTOTAL — a declared aggregation of the classified streams. Money for a sum, a bare number or `null` for a ratio whose denominator vanishes — a period the ratio is genuinely undefined in, which a declared metric's fold skips rather than reads as zero (`docs/03` §4). Like a field, it never enters model.total, model.npv, model.net_cash_flow or the per-stream annual rollup: it is an aggregation OF the cash, so counting it as cash would double what it touches. It carries no `offset`, because a subtotal spans streams that may settle at different points in a period and so has no single placement to claim.",
"additionalProperties": {
"$ref": "#/$defs/Series"
}
},
"DeterministicSection": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"metrics",
"series"
],
"properties": {
"status": {
"type": "string",
"enum": [
"not_run",
"ok",
"error"
]
},
"metrics": {
"$ref": "#/$defs/MetricMap"
},
"series": {
"$ref": "#/$defs/SeriesMap"
},
"errors": {
"type": "array",
"items": {
"$ref": "#/$defs/RuntimeError"
}
},
"annual_rollup": {
"$ref": "#/$defs/AnnualRollupSection"
},
"transitions": {
"type": "array",
"description": "Every state change an event made, in the order it happened — the audit trail for whether and when something occurred. Entity state is otherwise unobservable: nothing else distinguishes an event that fired against a misspelled target from an event that never fired, and without this a case cannot assert a transition. Recorded even when the value does not change, because the question the log answers is whether the event fired. Omitted when a model has no events. Visibility is two rules, not one: an event or option guard reads the state as the period OPENED, so declaration order cannot change an answer; a stream reads it as the period CLOSED, so a transition takes effect in the period it fires.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"period",
"date",
"entity",
"field",
"to",
"event"
],
"properties": {
"period": {
"type": "integer",
"minimum": 0
},
"date": {
"type": "string"
},
"entity": {
"type": "string"
},
"field": {
"type": "string"
},
"from": {
"type": "string",
"description": "The value before. Absent when the field had none — which, for a typed entity with a lifecycle, should not happen, because it opens in its declared initial state."
},
"to": {
"type": "string"
},
"event": {
"type": "string",
"description": "The event that fired. A transition always has a cause."
},
"master": {
"type": "string",
"description": "The master machine's word for `to`, on a status transition of a master machine or a refinement of one: `drawing` where the pack's word is `construction`. Lets a consumer find every debt in a phase across packs. Absent otherwise."
},
"resumed": {
"type": "string",
"description": "The enclosing state this transition re-entered by history: `to` is where the nested machine resumed, not a fresh entry — its entry actions did not run and its entry period is unchanged. Absent otherwise."
}
}
}
},
"trace": {
"$ref": "#/$defs/Trace"
},
"journal": {
"type": "array",
"description": "Every causal act the run performed, with what became of it, in the order the engine performed them. `transitions` records field CHANGES; the journal answers the question a reviewer asks — what did the model DO, and did each thing it was asked to do happen. An action that was declined, ignored or overridden changes nothing and so appears nowhere else: an `activate stream` that lost to the stream's own `active when` used to leave no trace at all. One row per act, and one row TYPE — an act whose effects are its own acts nests them as `children` rather than flattening them beside itself, which is what a transition and its arrival actions are (0.6). Omitted when a model has no events, options or waterfalls, so such a model publishes exactly what it published before.",
"items": {
"$ref": "#/$defs/JournalEntry"
}
}
}
},
"ScenariosSection": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"summaries"
],
"properties": {
"status": {
"type": "string",
"enum": [
"not_run",
"ok",
"error"
]
},
"summaries": {
"type": "array",
"items": {
"$ref": "#/$defs/ScenarioSummary"
}
},
"errors": {
"type": "array",
"items": {
"$ref": "#/$defs/RuntimeError"
}
}
}
},
"ScenarioSummary": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"metrics",
"series",
"ledger_hash"
],
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"ledger_hash": {
"type": "string",
"pattern": "^[0-9a-f]{64}$",
"description": "This scenario's outcome, hashed as the base run's `ledger_hash` is: its series and annual rollup without the pack's subtotals, its journal, transitions and trace."
},
"metrics": {
"$ref": "#/$defs/MetricMap"
},
"omitted": {
"type": "object",
"description": "Declared metrics this run could not evaluate, keyed as `metric.<name>`, each with the reason — a party that never received anything has no IRR to solve. Left out of `metrics` rather than published as zero or null; present only when non-empty. The deterministic run refuses instead (`E5031`).",
"additionalProperties": {
"type": "string"
}
},
"series": {
"$ref": "#/$defs/SeriesMap"
},
"annual_rollup": {
"$ref": "#/$defs/AnnualRollupSection"
},
"transitions": {
"type": "array",
"description": "Every state change an event made, in the order it happened — the audit trail for whether and when something occurred. Entity state is otherwise unobservable: nothing else distinguishes an event that fired against a misspelled target from an event that never fired, and without this a case cannot assert a transition. Recorded even when the value does not change, because the question the log answers is whether the event fired. Omitted when a model has no events. Visibility is two rules, not one: an event or option guard reads the state as the period OPENED, so declaration order cannot change an answer; a stream reads it as the period CLOSED, so a transition takes effect in the period it fires.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"period",
"date",
"entity",
"field",
"to",
"event"
],
"properties": {
"period": {
"type": "integer",
"minimum": 0
},
"date": {
"type": "string"
},
"entity": {
"type": "string"
},
"field": {
"type": "string"
},
"from": {
"type": "string",
"description": "The value before. Absent when the field had none — which, for a typed entity with a lifecycle, should not happen, because it opens in its declared initial state."
},
"to": {
"type": "string"
},
"event": {
"type": "string",
"description": "The event that fired. A transition always has a cause."
},
"master": {
"type": "string",
"description": "The master machine's word for `to`, on a status transition of a master machine or a refinement of one: `drawing` where the pack's word is `construction`. Lets a consumer find every debt in a phase across packs. Absent otherwise."
},
"resumed": {
"type": "string",
"description": "The enclosing state this transition re-entered by history: `to` is where the nested machine resumed, not a fresh entry — its entry actions did not run and its entry period is unchanged. Absent otherwise."
}
}
}
},
"journal": {
"type": "array",
"description": "Every causal act the run performed, with what became of it, in the order the engine performed them. `transitions` records field CHANGES; the journal answers the question a reviewer asks — what did the model DO, and did each thing it was asked to do happen. An action that was declined, ignored or overridden changes nothing and so appears nowhere else: an `activate stream` that lost to the stream's own `active when` used to leave no trace at all. One row per act, and one row TYPE — an act whose effects are its own acts nests them as `children` rather than flattening them beside itself, which is what a transition and its arrival actions are (0.6). Omitted when a model has no events, options or waterfalls, so such a model publishes exactly what it published before.",
"items": {
"$ref": "#/$defs/JournalEntry"
}
},
"trace": {
"$ref": "#/$defs/Trace"
},
"inputs": {
"$ref": "#/$defs/InputsSection"
},
"slices": {
"type": "array",
"items": {
"$ref": "#/$defs/SliceResult"
}
},
"domain_metrics": {
"$ref": "#/$defs/DomainMetrics"
},
"statements": {
"$ref": "#/$defs/StatementsSection"
}
},
"description": "One scenario's run, published whole: a scenario is a full deterministic run, so it carries what the base run carries: its series, rollup, journal and transitions, its slices, the review page as the scenario resolved it, and, where the run was enriched, its statements and domain metrics. The graph is the model's, published once at the root."
},
"MonteCarloSection": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"trials",
"seed",
"metrics",
"trial_summaries"
],
"properties": {
"status": {
"type": "string",
"enum": [
"not_run",
"ok",
"error"
]
},
"trials": {
"type": "integer",
"minimum": 1
},
"seed": {
"type": "integer",
"minimum": 0
},
"metrics": {
"type": "object",
"description": "Named Monte Carlo metric summaries",
"additionalProperties": {
"$ref": "#/$defs/MetricSummary"
}
},
"trial_summaries": {
"type": "array",
"items": {
"$ref": "#/$defs/TrialSummary"
}
},
"aggregates": {
"$ref": "#/$defs/MonteCarloAggregates"
},
"errors": {
"type": "array",
"items": {
"$ref": "#/$defs/RuntimeError"
}
},
"journal": {
"type": "array",
"description": "When each act happened across the trials, and how often — the question a stochastic run asks of the journal. A per-trial log is the wrong shape: trials x acts of output, and nobody reads ten thousand copies of the same sequence. So each distinct act gets one row, bounded by the model rather than the trial count, carrying the share of trials in which it occurred and the distribution over the period it FIRST did. Omitted when no trial recorded any act.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"actor",
"action",
"target",
"outcome",
"trials_occurred",
"share",
"first_period"
],
"properties": {
"actor": {
"type": "string",
"description": "The act's identity, matching the deterministic journal's own fields so a summary lines up against a single run's trail."
},
"action": {
"type": "string"
},
"target": {
"type": "string"
},
"outcome": {
"type": "string"
},
"trials_occurred": {
"type": "integer",
"minimum": 0,
"description": "Trials in which this act occurred at least once."
},
"share": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"first_period": {
"type": "object",
"additionalProperties": false,
"required": [
"min",
"p10",
"median",
"p90",
"max",
"mean"
],
"description": "Over the trials where the act occurred, the period it first did. Quantiles are nearest-rank order statistics rather than interpolated, because a quantile of periods should be a period: \"the covenant first broke around month 9\", not month 9.5. The mean stays fractional, being explicitly an average rather than an observation.",
"properties": {
"min": {
"type": "integer",
"minimum": 0
},
"p10": {
"type": "integer",
"minimum": 0
},
"median": {
"type": "integer",
"minimum": 0
},
"p90": {
"type": "integer",
"minimum": 0
},
"max": {
"type": "integer",
"minimum": 0
},
"mean": {
"type": "number",
"minimum": 0
}
}
}
}
}
},
"trace": {
"type": "array",
"description": "The trace across the trials: per actor, reason and state, the share of trials in which it occurred and the distribution over the period it first did. Sized by the model, not the trial count.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"actor",
"reason",
"trials_occurred",
"share",
"first_period"
],
"properties": {
"actor": {
"type": "string",
"description": "`lifecycle:<entity>`, `event:<name>`, `option:<name>`, `stream:<name>` or `field:<name>`."
},
"reason": {
"type": "string"
},
"state": {
"type": "string"
},
"trials_occurred": {
"type": "integer",
"minimum": 0
},
"share": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"first_period": {
"type": "object",
"additionalProperties": false,
"required": [
"min",
"p10",
"median",
"p90",
"max",
"mean"
],
"description": "Over the trials where the act occurred, the period it first did. Quantiles are nearest-rank order statistics rather than interpolated, because a quantile of periods should be a period: \"the covenant first broke around month 9\", not month 9.5. The mean stays fractional, being explicitly an average rather than an observation.",
"properties": {
"min": {
"type": "integer",
"minimum": 0
},
"p10": {
"type": "integer",
"minimum": 0
},
"median": {
"type": "integer",
"minimum": 0
},
"p90": {
"type": "integer",
"minimum": 0
},
"max": {
"type": "integer",
"minimum": 0
},
"mean": {
"type": "number",
"minimum": 0
}
}
}
}
}
},
"ledger_hash": {
"type": "string",
"pattern": "^[0-9a-f]{64}$",
"description": "The trials' outcome: a hash of this section as published without its `status`, `trials` and `seed`, which are the run's configuration. Absent when no trial ran and on one shard of a sharded run; the merged document carries the whole run's."
}
}
},
"TrialSummary": {
"type": "object",
"additionalProperties": false,
"required": [
"trial",
"metrics"
],
"properties": {
"trial": {
"type": "integer",
"minimum": 0
},
"metrics": {
"$ref": "#/$defs/MetricMap"
},
"omitted": {
"type": "object",
"description": "Declared metrics this run could not evaluate, keyed as `metric.<name>`, each with the reason — a party that never received anything has no IRR to solve. Left out of `metrics` rather than published as zero or null; present only when non-empty. The deterministic run refuses instead (`E5031`).",
"additionalProperties": {
"type": "string"
}
},
"npv": {
"type": "number",
"description": "On a trial shard only: the trial's NPV at full precision, which the whole run's aggregates are computed from, so the merge computes the same figures."
},
"journal": {
"type": "array",
"description": "On a trial shard only: each distinct act this trial performed and the period it first did, which the whole run's journal summary counts.",
"items": {
"$ref": "#/$defs/TrialJournalFirst"
}
},
"trace": {
"type": "array",
"description": "On a trial shard only: each actor's reasons this trial and the period each first held, which the whole run's trace summary counts.",
"items": {
"$ref": "#/$defs/TrialTraceFirst"
}
}
}
},
"MonteCarloAggregates": {
"type": "object",
"additionalProperties": false,
"required": [
"npv"
],
"properties": {
"npv": {
"$ref": "#/$defs/NpvAggregate"
}
}
},
"NpvAggregate": {
"type": "object",
"additionalProperties": false,
"required": [
"mean",
"median",
"stddev",
"p_negative"
],
"properties": {
"mean": {
"$ref": "#/$defs/Decimal"
},
"median": {
"$ref": "#/$defs/Decimal"
},
"stddev": {
"$ref": "#/$defs/Decimal"
},
"p_negative": {
"$ref": "#/$defs/Decimal"
}
}
},
"MetricSummary": {
"type": "object",
"additionalProperties": false,
"required": [
"type",
"mean",
"p50"
],
"properties": {
"type": {
"type": "string",
"enum": [
"number",
"money"
]
},
"trials": {
"type": "integer",
"minimum": 1,
"description": "How many trials published this metric. Not every trial publishes every name — `model.irr` exists only where the flows solve for a rate — so without this a mean over three trials and a mean over five hundred read identically."
},
"mean": {
"$ref": "#/$defs/Scalar"
},
"stdev": {
"$ref": "#/$defs/Scalar"
},
"min": {
"$ref": "#/$defs/Scalar"
},
"max": {
"$ref": "#/$defs/Scalar"
},
"p01": {
"$ref": "#/$defs/Scalar"
},
"p05": {
"$ref": "#/$defs/Scalar"
},
"p10": {
"$ref": "#/$defs/Scalar"
},
"p25": {
"$ref": "#/$defs/Scalar"
},
"p50": {
"$ref": "#/$defs/Scalar"
},
"p75": {
"$ref": "#/$defs/Scalar"
},
"p90": {
"$ref": "#/$defs/Scalar"
},
"p95": {
"$ref": "#/$defs/Scalar"
},
"p99": {
"$ref": "#/$defs/Scalar"
}
}
},
"RuntimeError": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string",
"minLength": 1
},
"message": {
"type": "string",
"minLength": 1
},
"path": {
"type": "string"
},
"hint": {
"type": "string"
}
}
},
"MetricLineage": {
"type": "object",
"additionalProperties": false,
"required": [
"numerator_streams",
"denominator_streams",
"formula"
],
"description": "Where a domain metric's value came from: the stream selectors it summed and the human-readable formula the pack declared. Emitted so a metric can be audited without reading the pack.",
"properties": {
"numerator_streams": {
"type": "array",
"items": {
"type": "string"
}
},
"denominator_streams": {
"type": "array",
"items": {
"type": "string"
}
},
"formula": {
"type": "string"
}
}
},
"DomainMetrics": {
"type": "object",
"additionalProperties": false,
"required": [
"pack",
"metrics",
"lineage"
],
"description": "Pack-defined metrics, present only when the run named a pack (`--pack <name>`). Engine-universal metrics live in `deterministic.metrics`; these are the domain's own, declared in the pack's metrics.toml.",
"properties": {
"pack": {
"type": "string"
},
"metrics": {
"$ref": "#/$defs/MetricMap"
},
"lineage": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/MetricLineage"
}
}
}
},
"AnnualRollupSection": {
"type": "object",
"additionalProperties": false,
"required": [
"series"
],
"description": "The deterministic series aggregated to annual buckets, for reporting a sub-annual model on a yearly grid. Present whenever the deterministic run succeeded. Carries no `offset`: an annual bucket sums periods whose placements differ.",
"properties": {
"series": {
"$ref": "#/$defs/SeriesMap"
}
}
},
"InputsSection": {
"type": "object",
"additionalProperties": false,
"description": "What went in, above the line items — the top of the audit chain. Absent when the model declares neither assumptions nor pack-lowered streams.",
"properties": {
"assumptions": {
"type": "array",
"items": {
"$ref": "#/$defs/AssumptionRow"
},
"description": "The review page: one row per assumption by full name, in name order, a set's fields each on their own row. In a deterministic run a random assumption resolves to its clipped CENTRAL value rather than to a draw; publishing it here is what stops that being invisible."
},
"streams": {
"type": "array",
"items": {
"type": "object"
},
"description": "Per-stream record of the contract terms a pack rule consumed to strike it, passed through from the IR's `stream_inputs` verbatim. See the IR schema's StreamInputs. Hand-written streams have no entry, because no rule struck them."
},
"quantiles": {
"type": "array",
"items": {
"$ref": "#/$defs/QuantileCall"
},
"description": "Which slice of a declared quantile each expression asked for, and what it resolved to. Passed through from the IR's quantile_inputs verbatim. A nonlinear input whose evaluation is not published is a number no reviewer can check: the top 2% of hours averaging 340.00 is the fact that explains the revenue, and the declaration alone does not state it."
}
}
},
"StatementsSection": {
"type": "object",
"additionalProperties": false,
"required": [
"statements"
],
"description": "Statements rendered against this run: the model's own declarations, the active pack's, or — when neither declares one — a default entity-hierarchy statement marked `default`. Rows carry order, labels, depth and a display sign; they compute nothing the engine has not already aggregated. Always present.",
"properties": {
"pack": {
"type": "string",
"description": "The pack whose statements these are. Absent when a MODEL declared them: a model-declared statement has no pack, and a sentinel string would be a value a consumer has to know to disregard."
},
"statements": {
"type": "array",
"items": {
"$ref": "#/$defs/Statement"
}
}
}
},
"Statement": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"label",
"default",
"grain",
"rows",
"reconciliation"
],
"properties": {
"id": {
"type": "string"
},
"label": {
"type": "string"
},
"default": {
"type": "boolean",
"description": "The statement to show when a reader asks for the statement rather than one by name. A pack marks one of its own, `default = true` in its `statements.toml` (the operating statement in each shipped pack); a model's own statement is never the default. With no statement declared by a pack or the model, the engine's fallback, `by_entity` (cash by entity), is the default. Advice about a stream's category that no statement row claims (`W5023`) is attached to the default statement's diagnostics."
},
"grain": {
"$ref": "#/$defs/StatementGrain"
},
"rows": {
"type": "array",
"items": {
"$ref": "#/$defs/StatementRow"
}
},
"reconciliation": {
"$ref": "#/$defs/StatementReconciliation"
},
"diagnostics": {
"type": "array",
"items": {
"$ref": "#/$defs/StatementDiagnostic"
},
"description": "Completeness findings. Empty is the healthy case."
},
"metrics": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Scalar"
},
"description": "Declared metrics published beside the statement. A metric is one number at the horizon and every row is a series, so the figures sit in their own map rather than as a row kind."
}
}
},
"StatementGrain": {
"type": "object",
"additionalProperties": false,
"description": "The grain this statement reports at, and one ready-to-render label per column. Published because a consumer cannot derive it: an annual statement over a monthly model has ten values where the model has 120, and nothing else in the document says which ten periods those are.",
"required": [
"calendar",
"start",
"labels"
],
"properties": {
"calendar": {
"type": "string",
"description": "monthly | quarterly | annual | daily — the bucketing, not the model grid."
},
"start": {
"type": "string"
},
"labels": {
"type": "array",
"items": {
"type": "string"
},
"description": "One per column, aligned with every row's `values`."
}
}
},
"StatementRow": {
"type": "object",
"additionalProperties": false,
"required": [
"kind",
"depth",
"display_sign"
],
"description": "One row. `residual` is emitted for cash no row claimed and cannot be authored; a `spacer` carries no values.",
"properties": {
"kind": {
"enum": [
"line",
"subtotal",
"ratio",
"spacer",
"residual"
]
},
"label": {
"type": "string"
},
"depth": {
"type": "integer",
"minimum": 0
},
"display_sign": {
"type": "number",
"enum": [
1,
-1
],
"description": "How to RENDER the sign. `values` is always the signed arithmetic quantity, so a consumer that ignores this still adds up correctly. -1 is how a deduction prints as a positive number in a 'less:' row while still being counted negatively — a line can be shown AND counted."
},
"values": {
"type": "array",
"items": {
"$ref": "#/$defs/SeriesValue"
}
},
"total": {
"type": "number",
"description": "Lifetime total. Absent for a ratio, where summing a column of ratios answers nothing, and for a spacer."
},
"streams": {
"type": "array",
"items": {
"type": "string"
},
"description": "The streams this row drew from — what makes a published figure traceable without a flow ledger."
},
"numerator": {
"type": "array",
"description": "A ratio row's numerator, at the statement's grain: a consumer that regroups the columns divides the sums of `numerator` and `denominator` rather than taking one period's ratio. Present on a declared ratio.",
"items": {
"$ref": "#/$defs/SeriesValue"
}
},
"denominator": {
"type": "array",
"description": "A ratio row's denominator, at the statement's grain; see `numerator`.",
"items": {
"$ref": "#/$defs/SeriesValue"
}
}
}
},
"StatementReconciliation": {
"type": "object",
"additionalProperties": false,
"required": [
"bottom_line",
"model_total",
"residual"
],
"description": "Does the statement account for the cash it is accountable for? Published always and asserted rather than corrected: a bottom line that quietly differs from the statement's universe is the failure this exists to make visible.",
"properties": {
"bottom_line": {
"type": "number"
},
"model_total": {
"type": "number",
"description": "The total of the statement's universe: model.total for an unfiltered statement, the slice's total when the statement declares one."
},
"residual": {
"type": "number"
}
}
},
"StatementDiagnostic": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
}
},
"SeriesValue": {
"description": "A series point: money, a bare number, or null where undefined."
},
"QuantileCall": {
"type": "object",
"required": [
"quantile",
"function"
],
"additionalProperties": false,
"properties": {
"quantile": {
"type": "string",
"description": "The quantile named at the call site."
},
"function": {
"type": "string",
"enum": [
"quantile_at",
"quantile_mean",
"quantile_of"
]
},
"args": {
"type": "array",
"items": {
"type": "number"
},
"description": "The literal arguments after the name, in source order. Absent — not empty — when they were not literals; `unresolved` says so."
},
"unresolved": {
"type": "boolean",
"description": "True when an argument is not a compile-time literal: it reads the period (`time.date`), a run input (`inputs.*`), or another computed value. No single resolved figure exists for such a call, so `args` and `value` are both absent and the call is listed on its name alone. Published rather than left implicit because the old shape was an empty `args` array, and every quantile function takes a fixed arity with at least one argument after the name — `quantile_mean` three, `quantile_of` and `quantile_at` two — so `[]` could never mean \"a call that took no arguments\" and read as exactly that."
},
"value": {
"type": "number",
"description": "What the call resolves to, rounded to the engine's published-number policy so it agrees exactly with the ledger figure it explains. ABSENT when an argument is not a literal — the call is still listed, because a silently omitted call site would read as a model that never made one."
}
}
},
"JournalEntry": {
"type": "object",
"additionalProperties": false,
"required": [
"period",
"date",
"actor",
"action",
"target",
"outcome"
],
"properties": {
"period": {
"type": "integer",
"minimum": 0
},
"date": {
"type": "string"
},
"actor": {
"type": "string",
"description": "Who acted, qualified by kind: `event:<name>`, `waterfall:<name>`, `option:<name>`, `stream:<name>`, `lifecycle:<id>`, and `contract:<name>` for a contract's term boundary (docs/01 §8.5). Qualified because a waterfall and an event may share a name and the log must not conflate them."
},
"action": {
"type": "string",
"enum": [
"fire",
"set",
"activate_stream",
"deactivate_stream",
"exercise_option",
"pay",
"inflow",
"allocate_in",
"allocate_out",
"move",
"transition"
]
},
"target": {
"type": "string",
"description": "What was acted on — a field path, a stream name, or a step and its payee."
},
"outcome": {
"type": "string",
"enum": [
"applied",
"declined",
"overridden",
"failed"
],
"description": "`applied` is the only one that changed anything. `declined` was refused for a stated reason. `overridden` was done and then lost to a stronger declaration — a stream activation against a false `active when`, or a waterfall step against a short pot. `failed` means the action's own expression did not evaluate. There is no `ignored`: an action kind the engine does not execute refuses the run before it starts (0.14)."
},
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"amount": {
"type": "number",
"description": "What the act moved: on a waterfall step, what the step allocated — allocated, not transferred: a waterfall is an ordered allocation over a pot, deciding what each step is entitled to out of what remains, and whether that cash physically settles is a question the language does not model; on an option's exercise, its payoff; on an account movement, the amount moved."
},
"pot_before": {
"type": "number",
"description": "The pot before the step drew on it, so a short pot is visible as the reason a step was allocated less than it was owed."
},
"pot_after": {
"type": "number"
},
"note": {
"type": "string",
"description": "Why, when the outcome is not `applied`."
},
"entity": {
"type": "string",
"description": "On an option's exercise: the entity its payoff is credited to, the one the option is written on, which the rollup credits."
},
"reads": {
"type": "object",
"description": "On an event's `fire` and a lifecycle's `transition`: each value the condition read, by the read as the IR writes it — a name, or a call that reads the model (a series, a curve, a draw, a state entry). The same values for every period the condition was tested are in the trace.",
"additionalProperties": true
},
"children": {
"type": "array",
"items": {
"$ref": "#/$defs/JournalEntry"
},
"description": "What this occurrence DID, when the occurrence and its effects are two different things. A transition's arrival actions are its children rather than its siblings because the tie between them is real: sharing a period and an entity only implies it, and a reader reconstructing which `set` belonged to which arrival would be guessing where several entities move in one period. Absent where an act has no composite effects, which is most of them."
}
},
"description": "One act, and what became of it. An act that DID something composite carries what it did as `children` — a transition is the occurrence, its arrival actions are its effects."
},
"GraphEntity": {
"type": "object",
"additionalProperties": false,
"required": [
"symbol",
"family"
],
"properties": {
"symbol": {
"type": "string",
"description": "The reference the model uses everywhere — `asset.tower`."
},
"family": {
"type": "string",
"description": "The family the compiler resolved from the entity's type — the root of its refinement chain — or the declaration's own word for an untyped entity. Never split from the symbol: the word and the type are checked to agree at compile (E1323).",
"enum": [
"asset",
"party",
"container",
"reference"
]
},
"type": {
"type": "string",
"description": "The ontology type the declaration states, when it states one."
},
"id": {
"type": "string",
"description": "The stable identity the model carries for a layer above it — the literal field `id`, engine-opaque, unique within the model (E1360)."
},
"parent": {
"type": "string",
"description": "The `part of` parent, when the model groups this entity."
},
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/PublishedValue"
},
"description": "The literal fields the model stated, keyed by field name, each with its declared type and unit — the area a rent roll reads beside a lease. `id` is published above and not repeated; a field that moves is a series under `field.`, not here. Absent when the entity states none."
}
}
},
"ResultsGraph": {
"type": "object",
"additionalProperties": false,
"required": [
"entities"
],
"description": "The model's graph, published so a consumer holding results alone can build the hierarchy view — who is part of what, what each thing is, the stable identity a governance layer assigned, and which agreements sit on which things. Values, not vocabulary: the pack's type roster lives in the pack; this is the graph THIS model declared.",
"properties": {
"entities": {
"type": "array",
"items": {
"$ref": "#/$defs/GraphEntity"
}
},
"contracts": {
"type": "array",
"items": {
"$ref": "#/$defs/GraphContract"
},
"description": "The contracts the model declared, each resolved to its type and master. Absent when the model declares none. With its terms, this is what a table over the graph reads (docs/01 §15.5): such a table is the renderer's and needs no declaration."
}
}
},
"SliceSelection": {
"type": "object",
"additionalProperties": false,
"properties": {
"entities": {
"type": "array",
"items": {
"type": "string"
}
},
"types": {
"type": "array",
"items": {
"type": "string"
}
},
"lines": {
"type": "array",
"items": {
"type": "string"
},
"description": "Lines by role the slice selected."
},
"categories": {
"type": "array",
"items": {
"type": "string"
}
},
"streams": {
"type": "array",
"items": {
"type": "string"
}
},
"except_streams": {
"type": "array",
"items": {
"type": "string"
}
},
"except_categories": {
"type": "array",
"items": {
"type": "string"
}
},
"except_entities": {
"type": "array",
"items": {
"type": "string"
}
},
"window": {
"$ref": "#/$defs/SliceWindow",
"description": "The reporting window, as declared. Published because it is the one part of a selection that removes cash a reader can still see in the series beside it, so the lineage has to state it."
}
}
},
"SliceResult": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"selection",
"streams",
"net",
"metrics"
],
"description": "A declared slice and what it came to (docs/01 §15.4): the selection as lineage, every stream it matched (empty is published, not omitted), the net per-period series, and total/npv/irr over the matched streams on the model's own axis. NO reconciliation block, by design — a slice is partial, and must be seen to be.",
"properties": {
"id": {
"type": "string"
},
"selection": {
"$ref": "#/$defs/SliceSelection"
},
"streams": {
"type": "array",
"items": {
"type": "string"
}
},
"net": {
"$ref": "#/$defs/Series"
},
"metrics": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/Scalar"
}
}
}
},
"SliceWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"from",
"to"
],
"description": "A slice's reporting bound, inclusive, normalized to YYYY-MM-DD.",
"properties": {
"from": {
"type": "string"
},
"to": {
"type": "string"
}
}
},
"GraphParty": {
"type": "object",
"additionalProperties": false,
"required": [
"role",
"entity"
],
"properties": {
"role": {
"type": "string",
"description": "The role as the model bound it — the pack's word (`landlord`)."
},
"master_role": {
"type": "string",
"description": "The master's word for the role (`lessor`), so a consumer finds every lender without knowing each pack's name for one."
},
"entity": {
"type": "string",
"description": "The party entity's symbol (`party.acme`)."
}
}
},
"GraphContract": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"type",
"subject",
"streams"
],
"properties": {
"name": {
"type": "string",
"description": "The contract's qualified name — `cre.lease_unit.tenant_a`."
},
"type": {
"type": "string",
"description": "The ontology type the contract IS — `CRE.Contract.UnitLease`; `core.Contract` where no type resolved."
},
"master": {
"type": "string",
"description": "The master at the root of the type's refinement chain — `Contract.Lease`."
},
"contract_name": {
"type": "string",
"description": "The pack's name for the type — the lowering rule name, `cre.lease_unit`."
},
"instance": {
"type": "string",
"description": "The instance token, where the name carries one — `tenant_a`."
},
"subject": {
"type": "string",
"description": "The entity the contract is written on (`asset.tower`)."
},
"parties": {
"type": "array",
"items": {
"$ref": "#/$defs/GraphParty"
},
"description": "Who the contract is between, by role."
},
"streams": {
"type": "array",
"items": {
"type": "string"
},
"description": "The streams the pack lowered from this contract, by name — the series published under `stream.<name>`."
},
"term": {
"type": "object",
"description": "The agreement's term as declared: `start` and `end` dates, or the state entry it opens at (`anchor_entity`, `anchor_state`, `anchor_periods`).",
"additionalProperties": false,
"properties": {
"start": {
"$ref": "#/$defs/Date"
},
"end": {
"$ref": "#/$defs/Date"
},
"anchor_entity": {
"type": "string"
},
"anchor_state": {
"type": "string"
},
"anchor_periods": {
"type": "integer"
}
}
},
"currency": {
"$ref": "#/$defs/Currency",
"description": "The currency the contract's money terms are stated in."
},
"terms": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/PublishedValue"
},
"description": "The terms the model stated, keyed by term name, each as the run resolved it. Absent when the contract states none."
}
}
},
"AssumptionRow": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"shape",
"type",
"value",
"origin"
],
"description": "One assumption on the review page.",
"properties": {
"name": {
"type": "string",
"description": "The full name a read uses: `cap_rate`, or `retail_market.new.ti_psf` for a set's field."
},
"shape": {
"type": "string",
"description": "`value`, `string`, or the distribution's kind (`Normal`, `LogNormal`, `Uniform`, `Triangular`)."
},
"type": {
"type": "string",
"description": "The language type: `Fraction`, `Rate`, `Decimal`, `Int` or `Duration`."
},
"unit": {
"type": "string",
"description": "The unit the model stated the value in, when it stated one."
},
"value": {
"type": [
"number",
"string",
"null"
],
"description": "What the base run resolved it to: a number, a string's text, or null when the assumption produced no number."
},
"set": {
"type": "object",
"additionalProperties": false,
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
}
},
"description": "The set this is a field of, when it is one, and the pack type that typed it."
},
"origin": {
"type": "string",
"enum": [
"model",
"run",
"file"
],
"description": "Which channel filled the row: the model's own statement, the run configuration's `inputs.<name>` override, or the inputs file, whose own `source` then stands in the row."
},
"source": {
"type": "object",
"additionalProperties": false,
"properties": {
"publisher": {
"type": "string"
},
"series": {
"type": "string"
},
"as_of": {
"type": "string"
},
"retrieved": {
"type": "string"
},
"url": {
"type": "string"
},
"note": {
"type": "string"
}
},
"description": "The `source` the row's value cites: the model's, for a value the model states; the inputs file entry's own, for a value the file supplies. Absent where the model cites none, and on a row the run configuration overrides, whose value the model's `source` does not describe."
}
}
},
"PublishedValue": {
"type": "object",
"additionalProperties": false,
"description": "A stated contract term or entity field as the run resolved it. Exactly one of three forms. A literal carries `value`. A read of one assumption (`inputs.<name>`) carries `reads`, and `value` when the assumption resolved to one number or text — the value on its review-page row, so a run's override shows; a series or a quantile has no single value and carries `reads` alone. Any other expression carries `expr` and no value: it is evaluated inside the streams that read it, and its effect is in their series. `type` and `unit` are the pack field's; a money figure is stated in the contract's `currency`.",
"properties": {
"type": {
"type": "string",
"description": "The declared type: `decimal`, `integer`, `number`, `string`, `date`, `account` or `contract`. Absent where no pack types the contract or entity."
},
"unit": {
"type": "string",
"description": "The declared unit (`USD/yr`, `ratio`, `months`, `sf`), when the pack states one. The pack's label: denominate money from the contract's `currency`."
},
"value": {
"description": "The value: a number, text, or a boolean.",
"type": [
"number",
"string",
"boolean"
]
},
"reads": {
"type": "string",
"description": "The assumption this term or field reads, `inputs.<name>`; its row is in `inputs.assumptions`."
},
"expr": {
"type": "string",
"description": "The expression as written, when it is neither a literal nor a single read."
}
}
},
"ShardRecord": {
"type": "object",
"additionalProperties": false,
"required": [
"kind"
],
"description": "This document is one shard of a sharded run, and which. The base shard carries the deterministic run and the scenarios and no trial; a trial shard carries the trials in its range and nothing else. Absent on a whole run and on a merged document, which is a whole run.",
"properties": {
"kind": {
"type": "string",
"enum": [
"base",
"trials"
]
},
"trials": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0
},
"minItems": 2,
"maxItems": 2,
"description": "A trial shard's range, [from, to), trials counted from 0."
},
"deferred": {
"type": "integer",
"minimum": 1,
"description": "On the base shard: the trials it left to the trial shards, which the merge must cover. Absent when the run declares no Monte Carlo."
}
}
},
"ShardSummary": {
"type": "object",
"additionalProperties": false,
"required": [
"shard",
"model_hash",
"ledger_hash",
"entities"
],
"properties": {
"shard": {
"type": "integer",
"minimum": 0
},
"model_hash": {
"type": "string"
},
"ledger_hash": {
"type": "string"
},
"entities": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"TrialJournalFirst": {
"type": "object",
"additionalProperties": false,
"required": [
"actor",
"action",
"target",
"outcome",
"first_period"
],
"properties": {
"actor": {
"type": "string"
},
"action": {
"type": "string"
},
"target": {
"type": "string"
},
"outcome": {
"type": "string"
},
"first_period": {
"type": "integer",
"minimum": 0
}
}
},
"ReasonRun": {
"type": "object",
"additionalProperties": false,
"required": [
"from",
"to",
"reason"
],
"properties": {
"from": {
"type": "integer",
"minimum": 0,
"description": "First period of the run."
},
"to": {
"type": "integer",
"minimum": 0,
"description": "Last period of the run, inclusive."
},
"reason": {
"type": "string",
"enum": [
"held",
"moved",
"set",
"no_state",
"not_scheduled",
"false",
"still_true",
"fired",
"disabled",
"outside_window",
"exhausted",
"exercised",
"ran",
"before_schedule",
"after_schedule",
"between_payments",
"outside_schedule",
"deactivated",
"out_of_state",
"closed",
"inactive",
"init",
"next",
"before_window",
"after_window"
],
"description": "Why. A lifecycle: `held` (no guarded edge from its state held), `moved` (an edge's guard held and the machine took it), `set` (an action wrote its state), `no_state`. An event: `not_scheduled`, `false`, `still_true` (an unscheduled condition still true, no new rising edge), `fired`, `disabled`. An option: `outside_window`, `not_scheduled`, `false`, `still_true`, `exercised`, `exhausted` (every exercise it allows taken), `disabled`. A stream: `ran` (its rule ran; the cell is its amount), `before_schedule`, `after_schedule`, `between_payments`, `outside_schedule` (no period of its schedule falls in the run) — a contract's stream takes its schedule from the contract's term — `deactivated` (by an action), `out_of_state` (a state its lifecycle does not run it in), `closed` (a sale above it closed it), `inactive` (its `active when` or `active in state` was false; `state` names the state its owner was in). A field: `init`, `next`, `held` (between its ticks), `before_window` and `after_window` (an anchored term not yet open, or over), `set` (an action wrote it)."
},
"state": {
"type": "string",
"description": "A lifecycle's state over the run, as the period's streams read it; on a stream, the state that excluded or closed it, or, when it is `inactive`, the state its owner was in."
},
"left": {
"type": "string",
"description": "On a lifecycle's `moved` or `set`: the state it left."
},
"tested": {
"type": "array",
"items": {
"type": "string"
},
"description": "A lifecycle's guarded edges tested and found false, `from -> to`, in the order tested."
},
"edge": {
"type": "string",
"description": "On a lifecycle's `moved`: the edge taken."
},
"entry": {
"type": "string",
"description": "The journal entry that caused the reason, by its position: `17`, or `17.2` for the third child of entry 17."
}
}
},
"Read": {
"type": "object",
"additionalProperties": false,
"required": [
"read"
],
"description": "One value a condition read, over the periods it was tested. Exactly one of `value`, `period`, `series` or `values` is present.",
"properties": {
"read": {
"type": "string",
"description": "The read as the IR writes it."
},
"value": {
"description": "The value, the same in every period tested."
},
"period": {
"type": "boolean",
"description": "The read is the period itself."
},
"series": {
"type": "string",
"description": "The published series the read equals in every period tested."
},
"lag": {
"type": "integer",
"minimum": 1,
"description": "How many periods back `series` is read; absent for the same period."
},
"values": {
"type": "array",
"description": "The value per period; `null` where the condition was not tested."
}
}
},
"Trace": {
"type": "object",
"additionalProperties": false,
"description": "Why every period is what it is. The journal records what the run did; the trace records what was decided in every period and why, including the periods in which nothing happened. Each actor's periods are runs of one reason, so the trace grows with the number of changes rather than of cells. It covers the cash horizon, aligned with the series. An amount is never repeated: a stream's cash is its series.",
"properties": {
"lifecycles": {
"type": "object",
"description": "Per entity with a state: its lifecycle's evaluation each period.",
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": [
"runs"
],
"properties": {
"lifecycle": {
"type": "string"
},
"runs": {
"type": "array",
"items": {
"$ref": "#/$defs/ReasonRun"
}
},
"edges": {
"type": "array",
"description": "What each guarded edge read, over the periods it was tested.",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"edge",
"when"
],
"properties": {
"edge": {
"type": "string"
},
"when": {
"type": "string"
},
"reads": {
"type": "array",
"items": {
"$ref": "#/$defs/Read"
}
}
}
}
}
}
}
},
"events": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/ConditionTrace"
}
},
"options": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/ConditionTrace"
}
},
"streams": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/$defs/ReasonRun"
}
}
},
"fields": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/$defs/ReasonRun"
}
}
}
}
},
"ConditionTrace": {
"type": "object",
"additionalProperties": false,
"required": [
"runs"
],
"properties": {
"when": {
"type": "string",
"description": "The condition: an event's `when`, an option's `exercise when`."
},
"runs": {
"type": "array",
"items": {
"$ref": "#/$defs/ReasonRun"
}
},
"reads": {
"type": "array",
"items": {
"$ref": "#/$defs/Read"
}
}
}
},
"TrialTraceFirst": {
"type": "object",
"additionalProperties": false,
"required": [
"actor",
"reason",
"first_period"
],
"properties": {
"actor": {
"type": "string"
},
"reason": {
"type": "string"
},
"state": {
"type": "string"
},
"first_period": {
"type": "integer",
"minimum": 0
}
}
}
}
}