Deal Engine — Core Design Overview
Purpose
This document is the architectural scaffold for the Deal Engine. It describes the core data model, composition layers, and design principles at the level needed for product and engineering leadership to evaluate and align on the fundamentals before detailed moving deeper into design.
Engineering details are deliberately omitted — sandboxing, registry storage, evaluation engine internals, and runtime concerns are out of scope here. This is the scaffold, not the whole building.
Several areas are known to need further definition once the core architecture is agreed upon:
- State management — How deals move through lifecycle states (draft, forecast, best case, signed, settled) and what each state means for computed fields and data completeness
- User overrides on calculated fields — How users can manually override engine-computed values, and what that means for recalculation and audit
- Cross-deal references — Whether clauses in one deal can reference data from another deal (Not sure of the need--AMS)
- Event Engine -- All details on event capture, etc.
- Interaction Model -- Details of systems interactions as shown in this PPT file (Box)
- Others TBD during review
1. What the Deal Engine Does
The Deal Engine transforms entertainment industry contracts into executable deal models. It focuses modeling exclusively on financial terms — compensation, guarantees, bonuses, reimbursements, and the conditions that govern when money is earned and received. The system handles deals across verticals: film, music, sports, fashion, and other entertainment sectors. Deal logic is expressed in JavaScript, replacing a prior custom DSL.
The core problem is this: entertainment deals are structurally complex. A touring contract might pay the greater of a fixed guarantee or a percentage of net proceeds, cross-collateralized across twenty shows, with per-show settlement triggers and a tour-level overage paid only after all shows settle. The Deal Engine makes these structures computable — turning contract language into models that can be evaluated, versioned, and audited as real-world events unfold.
2. The Three-Layer Model
The architecture has three layers of composition. Each layer has a distinct role.
Clause Types → Deal Types → Deal Instances
(components) (templates) (contracts)Clause Types are reusable, versioned components. Each clause type defines a single financial concept — a touring settlement, a base fee, a per diem reimbursement. It specifies a data schema, business logic (in JavaScript), and any external data dependencies. A clause type is written once and used across many deals.
For example, the touring-settlement clause type defines how touring payouts work: per-show versus comparisons, optional cross-collateralization, and tour-level aggregation. It doesn't know how many shows are on a particular tour or what the guarantees are — that's instance data.
Deal Types are templates that compose clause types into a deal structure. A deal type specifies which clauses are required, which are optional, and defines deal-level aggregation logic that rolls up clause-level results into deal totals. Deal types are thin by design — the business logic lives in the clauses; the deal type wires them together.
The music-touring deal type requires a touring-settlement clause and defines deal-level fields like total_guaranteed, total_earned, and deal_settled — computed by aggregating across the clause data.
Deal Instances are specific contracts with actual data. An instance references versioned clause types and deal types but contains no embedded logic. It is pure data: party information, show dates, guarantee amounts, settlement figures, and computed results. The "deal must compile" principle governs instance creation: all declared references must resolve, all required clauses must be present, and the dependency graph must be consistent.
A deal instance for a three-show summer tour contains the venues, dates, per-show guarantees, and — as shows settle — the box office revenue, expenses, and computed settlement amounts. The instance is a complete snapshot of the deal at any point in time.
3. How a Clause Type Works
A clause type is authored in YAML with JavaScript embedded in a logic field. It has four parts.
header: # Identity, classification, version
schema: # JSON Schema — complete state including earning structure
references: # Declared dependencies on deal-level data and other clause fields
logic: | # JavaScript — compute function + optional helpersSchema: The Unified State Model
The schema defines the complete state of the clause at any point in time. Input data, event states, and computed values are all fields in one schema. There is no separate computed state section — the instance data is the state.
Computed fields carry a computed: true annotation, which tells the engine which fields are logic-written and tells UIs which fields are not user-editable:
# From the touring-settlement clause type
schema:
type: object
properties:
artist_percentage:
type: number # ← Input: entered by a human
cross_collateralized:
type: boolean # ← Input: deal parameter
shows:
type: array
items:
type: object
properties:
venue:
type: string # ← Input: per-show data
guarantee:
type: number # ← Input: contractual floor
settled:
type: boolean # ← Event state: has this show settled?
net_proceeds:
type: number
computed: true # ← Computed: gross minus expenses
artist_share:
type: number
computed: true # ← Computed: net proceeds × artist percentage
all_shows_settled:
type: boolean
computed: true # ← Computed: derived from collection statecomputed: true is recursive. The annotation works at any depth — top-level fields, fields inside nested objects, and fields inside array items. The engine discovers computed fields by walking the schema recursively, including into items.properties for arrays. No special mechanism is needed for nested computed fields.
Earning Structure
Financial clauses express their financial structure as an earning object in the schema, grouping the computed amount with its earning and receipt schedules:
earning:
type: object
properties:
amount:
type: number
computed: true # The payout amount, computed by logic
earning_schedule:
$ref: Schedule # When the amount is earned (accounting)
receipt_schedule:
$ref: Schedule # When cash arrives (cash flow)This structure makes explicit a universal distinction in agency deals: when revenue is recognized (earned) versus when cash arrives (received). Every financial clause has these two timing dimensions.
Earning objects can appear at multiple levels of a schema. In a touring deal, each show has its own earning (the per-show payout, with schedules triggered by that show's settlement), and the clause has a separate earning (the cross-collateralization overage, with schedules triggered by all shows settling). Each earning stands alone as an independent financial event.
An earning object may also include additional computed: true context fields beyond amount. The clause-level touring earning includes total_guarantees and total_artist_share — these explain why the overage is what it is. The earning object tells a self-contained settlement story.
The clause's classification (in the header) tells the engine which clauses have an earning structure and what accounting treatment applies.
References
A clause's references section declares every external dependency — deal-level fields and fields from other clauses. This is the only way logic accesses data outside its own schema.
references:
currency: deal.currencyThe engine resolves all declared references before calling the logic and passes them as the refs parameter. Logic cannot access undeclared external data. All references are validated at deal compile time — missing or broken references are caught before evaluation.
References also define the clause's dependency graph. The engine uses this graph to determine evaluation order: clauses are evaluated after their dependencies.
The Compute Contract
The logic field contains a compute function as the entry point. The engine calls it with a structured input. The function writes computed values directly into the data object — there is no return value.
function compute({ data, refs }) {
// data: the clause instance data (full schema, all fields)
// refs: resolved values from the references section
// Writes directly to data — no return value
}The clause owns its schema. compute writes to computed: true fields in place. For collections, this means iterating the array and writing to each item directly:
// From the touring-settlement clause type
function computeShow(show, artistPercentage, crossCollateralized) {
if (!show.settled) {
show.net_proceeds = null;
show.artist_share = null;
show.earning.amount = null;
return;
}
show.net_proceeds = show.gross_box_office - show.expenses;
show.artist_share = show.net_proceeds * artistPercentage;
show.earning.amount = crossCollateralized
? show.guarantee
: Math.max(show.guarantee, show.artist_share);
}
function compute({ data, refs }) {
for (const show of data.shows) {
computeShow(show, data.artist_percentage, data.cross_collateralized);
}
// ... clause-level aggregation follows ...
}Helper functions (like computeShow above) are permitted alongside compute in the logic block. compute is the entry point the engine calls; helpers are internal.
The function must be pure in the sense that matters: no side effects beyond writing to the provided data object, no network, no randomness. Same inputs → same outputs.
4. How a Deal Type Works
A deal type is a thin composition layer. It defines deal-level data, specifies which clauses form the deal, and provides aggregation logic that rolls up clause results.
header:
id: music-touring
version: 1.0.0
name: "Music Touring Deal"
department: music
schema:
type: object
properties:
parties:
type: object
properties:
talent: { $ref: "authoritative://schemas/talent" }
promoter: { $ref: "authoritative://schemas/promoter" }
currency:
type: string
default: USD
total_guaranteed:
type: number
computed: true
total_earned:
type: number
computed: true
deal_settled:
type: boolean
computed: true
clauses:
tour_settlement:
clause_type: touring-settlement
required: true
logic: |
function compute({ deal_data, clauses }) {
const settlement = clauses.tour_settlement;
deal_data.total_guaranteed = settlement.total_show_guarantees;
const showEarnings = settlement.shows
.reduce((sum, s) => sum + (s.earning.amount ?? 0), 0);
const clauseEarning = settlement.earning.amount ?? 0;
deal_data.total_earned = showEarnings + clauseEarning;
deal_data.deal_settled = settlement.all_shows_settled;
}Clause Composition
Deal types specify required and optional clauses. Required clauses must be present in any conforming instance. Optional clauses may be included or omitted. Clauses not mentioned in the deal type are permitted in an instance as long as the deal compiles — all references resolve and logic is consistent.
This means deal types suggest a structure but do not rigidly constrain it. A touring deal that adds a per diem reimbursement clause not listed in the deal type is valid if it compiles. Deal types are starting-point templates, not straitjackets.
Deal-Level Compute
The deal type's compute function receives all clause data (after clause-level evaluation) and writes to deal-level computed fields:
function compute({ deal_data, clauses }) {
// deal_data: deal-level schema (all fields)
// clauses: object keyed by clause_id, each containing full clause data
// Writes directly to deal_data — no return value
}Deal-level logic aggregates; clause-level logic computes. The deal type reads computed values from clauses and rolls them up — it doesn't recompute show-level or clause-level logic.
5. How a Deal Instance Works
A deal instance is pure data. It references versioned type identifiers but contains no embedded logic. To evaluate a deal, the system resolves the referenced types from an immutable type version registry and executes their JavaScript against the instance data.
{
"instance_metadata": {
"instance_id": "deal-2026-touring-002",
"status": "active",
"current_version": 1
},
"type_references": {
"deal_type": { "id": "music-touring", "version": "1.0.0" },
"clause_types": {
"tour_settlement": { "id": "touring-settlement", "version": "1.0.0" }
}
},
"version_info": {
"version": 1,
"effective_date": "2026-03-15",
"change_type": "initial"
},
"deal_data": {
"parties": { "talent": { "name": "Aurora Vega" }, "promoter": { "name": "Live Nation" } },
"currency": "USD",
"total_guaranteed": 185000,
"total_earned": 125000,
"deal_settled": false
},
"clauses": [
{
"clause_id": "tour_settlement",
"data": {
"artist_percentage": 0.85,
"cross_collateralized": true,
"shows": [ "..." ],
"all_shows_settled": false,
"total_show_guarantees": 185000,
"earning": { "amount": null }
}
}
]
}The instance is a complete, self-describing snapshot. Input data, event states, and computed values all live in the same schema. Computed fields start as null in a new instance and are populated by the engine on evaluation. After evaluation, anyone reading the instance JSON can see the full state of the deal without locating a separate computed section or correlating fields across structures.
Logic is not stored in the instance. The type_references point to the authoritative JavaScript in the registry. This separates data (which changes per-deal and per-event) from logic (which is shared across all instances of a type).
6. Clause Classification
Clauses are classified in a hierarchical taxonomy that determines their financial treatment and what sub-attributes apply.
Category (top level):
| Category | Description | Value Types | Guarantee/Contingent? |
|---|---|---|---|
| Financial | Monetary flows | earning, reimbursement | Yes |
| Value | Non-monetary value provided | third_party, in_kind | Yes |
| Obligation | Actions to be taken, not financial | (none) | No |
| Other | Catch-all for unclassified clauses | (none) | No |
Guarantee vs. Contingent applies to Financial and Value clauses. A guarantee is a certain obligation when conditions are met. A contingent clause is conditional on event occurrence.
Examples:
| Clause | Category | Value Type | Attribute |
|---|---|---|---|
| Base performance fee | Financial | earning | guarantee |
| Performance bonus | Financial | earning | contingent |
| Per diem | Financial | reimbursement | guarantee |
| Publicist fee | Value | third_party | guarantee |
| Wardrobe allowance | Value | in_kind | guarantee |
| Extra wardrobe if option exercised | Value | in_kind | contingent |
| Exclusivity terms | Obligation | — | — |
| Territory rights | Obligation | — | — |
The classification lives in the clause type header and tells the engine which clauses have earning structures, what accounting treatment applies, and how to categorize financial flows in reporting.
7. Key Design Principles
Unified State Model
The JSON schema defines the complete state of a clause or deal at any point in time. Input data, event states, and computed values are all fields in one schema. Computed fields carry a computed: true annotation — recursive into nested objects and array items. There is no separate computed state section. The instance is the state.
Direct-Mutation Compute Contract
compute writes directly to the data object it receives. There is no return value. The clause owns its schema — all fields (input and computed) live in one structure. A separate return object that the engine merges back introduces an intermediate step with no benefit. The computed: true annotations tell the engine which fields are logic-written, serving the same purpose a return-value contract would, without the extra mechanism.
Earned vs. Received Separation
Every financial clause tracks two independent timing dimensions: when revenue is earned (accounting recognition) and when cash is received (cash flow). These are expressed structurally as separate schedules within the earning object. This distinction is universal in agency deals and is baked into the data model, not left to convention.
Explicit References and Compile-Time Validation
A clause's references section declares every external dependency. The engine resolves references before calling compute and passes them as refs. Logic cannot access undeclared external data. All references are validated when a deal is compiled — missing or broken references are caught before evaluation, not discovered at runtime.
Collection Count Is Data, Not Type
A single-show tour and a twenty-show tour use the same clause type. The shows array has a different length; the logic is identical. Behavioral parameters like cross_collateralized are schema fields, not reasons for separate types. Variation is expressed through parameters and composition (multiple clause instances), not type proliferation.
Collections Grow Over Time
Collections don't have to be fixed at deal creation. Dynamic occurrences — optional social media posts at talent's discretion, overage production hours, additional performances — are modeled as collection items added to the instance as they happen. Each addition creates a new immutable version and triggers full recalculation. The clause type defines the schema and rate structure; the collection starts empty or sparse; items appear as real-world events occur. This uses the same collection + immutable versioning + recalculation pattern as pre-defined collections — no special mechanism needed.
Determinism
Same inputs produce the same outputs — across time, environments, and machines. This supports replay, audit, cross-language agreement, and fingerprint-based caching. Canonical JSON (RFC 8785/JCS) is required for serialization.
8. Event System, Versioning, and Amendments
Events
Events use a three-state model: unknown, true, or false. Events are composable — events can reference other events. Complete transition history is maintained for audit. The Deal Engine publishes state changes but does not orchestrate downstream systems.
Conditions derived from collection data (e.g., all_shows_settled = every(show => show.settled)) are expressed as computed: true booleans, not as special event constructs. They gate downstream computation like any computed field.
Versioning
Every data update, clause amendment, or structural change creates a new immutable version of the deal instance. Each version is a complete snapshot. The version chain provides the full audit trail. Full recalculation runs on every evaluation — no incremental computation. Because computed values live alongside input data in the schema, the instance is always a complete snapshot after evaluation.
Amendments
When logic needs to change for an existing deal (contract amendment), the instance's type reference is updated to point to a new type version, a new instance version is created, and full recalculation runs against the new logic. Prior versions retain their state as historical record, with their original type references intact.
9. Open Questions
Template section: The clause type structure includes a template section for contract text rendering. Whether this moves to JavaScript (like business logic) or remains declarative is unresolved.
Deal instance states: Deals move through states — draft, forecast, best case, signed, settled. How these states interact with the data model is not yet defined. One open question is whether null field values in certain states represent missing data or walk-away potential (the deal terms if one party walks away at the current stage of negotiation).
10. Appendix: Worked Example — Multi-Show Touring Deal
This appendix contains the complete touring deal: clause type, deal type, deal instance, and evaluation walkthrough. Three shows, two settled, one unsettled. The deal is fully cross-collateralized.
Clause Type: touring-settlement
# ============================================================
# Clause Type: touring-settlement
# Multi-show touring with per-show versus and optional
# cross-collateralization at the tour level
# ============================================================
header:
id: touring-settlement
version: 1.0.0
category: financial
value_type: earning
attribute: guarantee
name: "Touring Settlement"
description: >
Touring payout across one or more shows. Each show pays the greater
of its guarantee or the artist's percentage of net proceeds.
When cross-collateralized, a tour-level versus may produce an
additional overage above the sum of per-show guarantees.
schema:
type: object
required:
- artist_percentage
- cross_collateralized
- shows
properties:
# --- Clause-level input fields ---
artist_percentage:
type: number
minimum: 0
maximum: 1
description: "Artist's share of net proceeds (e.g., 0.85 for 85%); applies to all shows"
cross_collateralized:
type: boolean
description: >
When true, a tour-level versus (aggregate guarantee vs. aggregate percentage)
determines whether an additional overage is owed above per-show guarantees.
When false, each show settles independently at its own versus result.
# --- Shows collection ---
shows:
type: array
items:
type: object
required:
- venue
- show_date
- guarantee
properties:
# Per-show input fields
venue:
type: string
description: Venue name
show_date:
type: string
format: date
description: Performance date
guarantee:
type: number
minimum: 0
description: Fixed guarantee floor for this show
gross_box_office:
type: number
minimum: 0
description: Total box office revenue (null before settlement)
expenses:
type: number
minimum: 0
description: Deductible expenses (null before settlement)
# Per-show event state
settled:
type: boolean
default: false
description: Whether this show has been financially settled
# Per-show computed fields
net_proceeds:
type: number
computed: true
description: Gross box office minus expenses
artist_share:
type: number
computed: true
description: "Artist's percentage of this show's net proceeds"
show_versus_result:
type: number
computed: true
description: Greater of guarantee or artist share (informational in cross-coll)
show_guarantee_won:
type: boolean
computed: true
description: True if the guarantee exceeded the percentage share for this show
# Per-show earning
earning:
type: object
properties:
amount:
type: number
computed: true
description: >
Cross-collateralized: the show's guarantee.
Non-cross-collateralized: the show's versus result.
earning_schedule:
$ref: Schedule
receipt_schedule:
$ref: Schedule
# --- Clause-level computed fields ---
all_shows_settled:
type: boolean
computed: true
description: True when every show in the collection has settled
total_show_guarantees:
type: number
computed: true
description: Sum of all show guarantees (always computable — guarantees are contract terms)
total_net_proceeds:
type: number
computed: true
description: Sum of net proceeds across all shows (null until all settled)
tour_artist_share:
type: number
computed: true
description: "Artist's percentage of aggregate net proceeds (null until all settled)"
tour_versus_result:
type: number
computed: true
description: Greater of total guarantees or tour artist share (null until all settled)
tour_guarantee_won:
type: boolean
computed: true
description: True if aggregate guarantees exceeded aggregate percentage (null until all settled)
# --- Clause-level earning (cross-collateralization settlement) ---
earning:
type: object
properties:
total_guarantees:
type: number
computed: true
description: Sum of all show guarantees (aggregate floor) — financial context for the overage
total_artist_share:
type: number
computed: true
description: "Artist's percentage of aggregate net proceeds — financial context for the overage"
amount:
type: number
computed: true
description: >
Cross-collateralization overage: max(0, total_artist_share - total_guarantees).
Zero when tour guarantees win or when not cross-collateralized.
Null until all shows settle.
earning_schedule:
$ref: Schedule
receipt_schedule:
$ref: Schedule
references:
currency: deal.currency
logic: |
function computeShow(show, artistPercentage, crossCollateralized) {
if (!show.settled) {
show.net_proceeds = null;
show.artist_share = null;
show.show_versus_result = null;
show.show_guarantee_won = null;
show.earning.amount = null;
return;
}
show.net_proceeds = show.gross_box_office - show.expenses;
show.artist_share = show.net_proceeds * artistPercentage;
show.show_versus_result = Math.max(show.guarantee, show.artist_share);
show.show_guarantee_won = show.guarantee >= show.artist_share;
show.earning.amount = crossCollateralized
? show.guarantee
: show.show_versus_result;
}
function compute({ data, refs }) {
// --- Per-show computation ---
for (const show of data.shows) {
computeShow(show, data.artist_percentage, data.cross_collateralized);
}
// --- Tour-level aggregation ---
data.all_shows_settled = data.shows.every(s => s.settled);
data.total_show_guarantees = data.shows.reduce((sum, s) => sum + s.guarantee, 0);
if (data.all_shows_settled) {
data.total_net_proceeds = data.shows.reduce((sum, s) => sum + s.net_proceeds, 0);
data.tour_artist_share = data.total_net_proceeds * data.artist_percentage;
data.tour_versus_result = Math.max(data.total_show_guarantees, data.tour_artist_share);
data.tour_guarantee_won = data.total_show_guarantees >= data.tour_artist_share;
// --- Clause-level earning (cross-collateralization settlement) ---
data.earning.total_guarantees = data.total_show_guarantees;
data.earning.total_artist_share = data.tour_artist_share;
data.earning.amount = data.cross_collateralized
? Math.max(0, data.tour_versus_result - data.total_show_guarantees)
: 0;
} else {
data.total_net_proceeds = null;
data.tour_artist_share = null;
data.tour_versus_result = null;
data.tour_guarantee_won = null;
data.earning.total_guarantees = null;
data.earning.total_artist_share = null;
data.earning.amount = null;
}
}Deal Type: music-touring
# ============================================================
# Deal Type: music-touring
# Touring deal with one or more settlement clauses
# ============================================================
header:
id: music-touring
version: 1.0.0
name: "Music Touring Deal"
description: >
Standard touring contract. Talent performs one or more shows.
Settlement may be per-show or cross-collateralized across shows.
department: music
tags:
- touring
- live-events
- versus
schema:
type: object
required:
- parties
- dates
- currency
properties:
# --- Input fields ---
parties:
type: object
required:
- talent
- promoter
properties:
talent:
$ref: "authoritative://schemas/talent"
promoter:
$ref: "authoritative://schemas/promoter"
agency:
$ref: "authoritative://schemas/agency"
dates:
type: object
required:
- effective_date
properties:
effective_date:
type: string
format: date
currency:
type: string
default: USD
tour_info:
type: object
properties:
tour_name:
type: string
territory:
type: string
# --- Computed fields (populated by deal-level logic) ---
total_guaranteed:
type: number
computed: true
description: Sum of all show guarantees across all settlement clauses
total_earned:
type: number
computed: true
description: Current total earned (per-show earnings + any cross-coll overage)
deal_settled:
type: boolean
computed: true
description: True when all settlement clauses have all shows settled
clauses:
tour_settlement:
clause_type: touring-settlement
required: true
description: "Tour show settlement — per-show versus with optional cross-collateralization"
logic: |
function compute({ deal_data, clauses }) {
const settlement = clauses.tour_settlement;
deal_data.total_guaranteed = settlement.total_show_guarantees;
const showEarnings = settlement.shows
.reduce((sum, s) => sum + (s.earning.amount ?? 0), 0);
const clauseEarning = settlement.earning.amount ?? 0;
deal_data.total_earned = showEarnings + clauseEarning;
deal_data.deal_settled = settlement.all_shows_settled;
}Deal Instance: Summer Arena Tour (3 shows, 2 settled)
{
"instance_metadata": {
"instance_id": "deal-2026-touring-002",
"status": "active",
"created_at": "2026-03-15T10:00:00Z",
"created_by": "agent@uta.com",
"current_version": 1
},
"type_references": {
"deal_type": {
"id": "music-touring",
"version": "1.0.0"
},
"clause_types": {
"tour_settlement": {
"id": "touring-settlement",
"version": "1.0.0"
}
}
},
"version_info": {
"version": 1,
"effective_date": "2026-03-15",
"prior_version": null,
"change_type": "initial",
"change_summary": "Deal created — 2 of 3 shows settled"
},
"deal_data": {
"parties": {
"talent": {
"name": "Aurora Vega",
"talent_id": "talent-avega-001"
},
"promoter": {
"name": "Live Nation Entertainment",
"entity_id": "promoter-livenation-001"
},
"agency": {
"name": "UTA",
"entity_id": "agency-uta-001"
}
},
"dates": {
"effective_date": "2026-03-15"
},
"currency": "USD",
"tour_info": {
"tour_name": "Summer Arena Tour 2026",
"territory": "North America"
},
"total_guaranteed": 185000,
"total_earned": 125000,
"deal_settled": false
},
"clauses": [
{
"clause_id": "tour_settlement",
"data": {
"artist_percentage": 0.85,
"cross_collateralized": true,
"shows": [
{
"venue": "Madison Square Garden",
"show_date": "2026-07-12",
"guarantee": 75000,
"gross_box_office": 150000,
"expenses": 82000,
"settled": true,
"net_proceeds": 68000,
"artist_share": 57800,
"show_versus_result": 75000,
"show_guarantee_won": true,
"earning": {
"amount": 75000,
"earning_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled"
},
"receipt_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled",
"payment_terms_days": 30
}
}
},
{
"venue": "The Forum",
"show_date": "2026-07-19",
"guarantee": 50000,
"gross_box_office": 320000,
"expenses": 95000,
"settled": true,
"net_proceeds": 225000,
"artist_share": 191250,
"show_versus_result": 191250,
"show_guarantee_won": false,
"earning": {
"amount": 50000,
"earning_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled"
},
"receipt_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled",
"payment_terms_days": 30
}
}
},
{
"venue": "Red Rocks Amphitheatre",
"show_date": "2026-07-26",
"guarantee": 60000,
"gross_box_office": null,
"expenses": null,
"settled": false,
"net_proceeds": null,
"artist_share": null,
"show_versus_result": null,
"show_guarantee_won": null,
"earning": {
"amount": null,
"earning_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled"
},
"receipt_schedule": {
"pattern": "event_triggered",
"trigger_event": "settled",
"payment_terms_days": 30
}
}
}
],
"all_shows_settled": false,
"total_show_guarantees": 185000,
"total_net_proceeds": null,
"tour_artist_share": null,
"tour_versus_result": null,
"tour_guarantee_won": null,
"earning": {
"total_guarantees": null,
"total_artist_share": null,
"amount": null,
"earning_schedule": {
"pattern": "event_triggered",
"trigger_event": "all_shows_settled"
},
"receipt_schedule": {
"pattern": "event_triggered",
"trigger_event": "all_shows_settled",
"payment_terms_days": 45
}
}
}
}
],
"archived_clauses": []
}Evaluation Walkthrough
Current State: 2 of 3 Shows Settled
1. READ type_references
→ deal_type: music-touring@1.0.0
→ clause_types.tour_settlement: touring-settlement@1.0.0
2. RESOLVE types from registry
→ Fetch YAML definitions, extract JS logic
3. EVALUATE clause: tour_settlement
Engine calls touring-settlement compute() with:
data = clauses[0].data
refs = { currency: "USD" }
Per-show iteration:
Show 1 — Madison Square Garden (settled):
net_proceeds: 150000 - 82000 = 68000
artist_share: 68000 × 0.85 = 57800
show_versus_result: max(75000, 57800) = 75000
show_guarantee_won: true (75000 ≥ 57800)
earning.amount: 75000 (cross-coll → guarantee)
Show 2 — The Forum (settled):
net_proceeds: 320000 - 95000 = 225000
artist_share: 225000 × 0.85 = 191250
show_versus_result: max(50000, 191250) = 191250
show_guarantee_won: false (50000 < 191250)
earning.amount: 50000 (cross-coll → guarantee)
Show 3 — Red Rocks Amphitheatre (not settled):
All computed fields → null
earning.amount → null
Tour-level aggregation:
all_shows_settled: false (show 3 pending)
total_show_guarantees: 75000 + 50000 + 60000 = 185000
total_net_proceeds: null (not all settled)
tour_artist_share: null
tour_versus_result: null
tour_guarantee_won: null
earning.total_guarantees: null (not all settled)
earning.total_artist_share: null
earning.amount: null (cross-coll can't finalize)
4. EVALUATE deal-level logic
Engine calls music-touring compute() with:
deal_data = { parties, dates, currency, tour_info, ... }
clauses = { tour_settlement: <clause data above> }
total_guaranteed: 185000 (from clause)
total_earned: 75000 + 50000 + 0 + 0 = 125000 (settled show earnings only)
deal_settled: false
5. STORE as immutable version 1What Changes When Red Rocks Settles
When show 3 settles (gross_box_office = 200,000, expenses = 70,000), a new version is created:
Show 3 — Red Rocks Amphitheatre (now settled):
net_proceeds: 200000 - 70000 = 130000
artist_share: 130000 × 0.85 = 110500
show_versus_result: max(60000, 110500) = 110500
show_guarantee_won: false
earning.amount: 60000 (cross-coll → guarantee)
Tour-level aggregation (now complete):
all_shows_settled: true
total_show_guarantees: 185000
total_net_proceeds: 68000 + 225000 + 130000 = 423000
tour_artist_share: 423000 × 0.85 = 359550
tour_versus_result: max(185000, 359550) = 359550
tour_guarantee_won: false (percentage wins at tour level)
earning.total_guarantees: 185000
earning.total_artist_share: 359550
earning.amount: 359550 - 185000 = 174550 (cross-coll overage)
Deal-level:
total_guaranteed: 185000
total_earned: 75000 + 50000 + 60000 + 174550 = 359550
deal_settled: trueVerification: Total talent payout (sum of per-show guarantees + cross-coll overage) = 185,000 + 174,550 = 359,550, which equals the tour versus result. ✓
The cross-collateralization effect: Without cross-collateralization, per-show versus results would total 75,000 + 191,250 + 110,500 = 376,750. The cross-collateralized tour pays 359,550 — the aggregate pool reduces the total because show 1's guarantee subsidy (75,000 vs. 57,800 standalone) gets offset at the tour level. Cross-collateralization benefits the promoter.