Skip to content

Deal Engine Architecture Proposal: Clause Types, Deal Types, and Deal Instances

Version: 2.0
Last Updated: January 2026

Overview

The Deal Engine v2 architecture uses a Clause Type Composition Model to transform entertainment contracts into executable deal models. The architecture separates structure (defined in DSL) from data (provided in JSON), enabling reusable building blocks that compose into complete deals.

mermaid
flowchart LR
    subgraph Catalog["Design-Time Catalog"]
        CT[Clause Types]
        DT[Deal Types]
    end
    
    subgraph Runtime["Runtime"]
        DI[Deal Instance]
    end
    
    CT -->|"copied into"| DI
    DT -->|"guides creation"| DI
    
    style DI fill:#e1f5fe

The system consists of three core components:

ComponentPurposeLifetime
Clause TypeReusable financial arrangement templateDesign-time
Deal TypeTemplate suggesting clause combinationsDesign-time
Deal InstanceSelf-contained executable contractRuntime

Clause Types

A Clause Type defines a reusable financial arrangement—the building block of deals. Each clause type answers the fundamental financial questions: how much, when earned, and when received.

Structure

Clause Types define a set of data and calculations that capture the logic of a component of a deal. Each Clause Type contains the following sections.

SectionPurpose
headerIdentity and classification (id, version, category, value_type, name)
schemaJSON Schema defining the data structure for this clause
inputsDeclarations of deal-level data this clause needs access to
logicEvents, computations, and for_each iterations that process data
financialCore financial interface: amount, earned timing, received timing
outputsValues exposed to deal-level logic and other clauses
templateContract text rendering with variable substitution

Two-Dimensional Classification

Every clause is classified along two orthogonal dimensions. Category determines certainty of obligation; Value Type determines the nature of value:

earningreimbursementthird_partyin_kind
guaranteeBase feePer diemPublicist feeWardrobe allowance
contingentPerformance bonusTravel if extendedStylist if awardsExtra wardrobe if option
simple(non-financial: exclusivity, territory rights, etc.)

This two-dimensional classification enables accurate aggregation for commissions, accounting, and reporting—a guarantee reimbursement is treated differently than a contingent earning.

Earned vs. Received

Every financial clause has two timing dimensions, reflecting the separation of revenue recognition and cash flow:

DimensionQuestionBusiness Concept
EarnedWhen is the value recognized?Revenue recognition (accounting)
ReceivedWhen is cash received?Cash flow

A show may be earned when it plays (revenue is recognized), but cash may not be received until 30-60 days later. The architecture tracks both independently.

Financial Section

The financial section is the core interface for guarantee and contingent clauses:

financial {
  amount: total_earned              // How much?
  earned: on earning_schedule       // When earned? (revenue recognition)
  received: on receipt_schedule     // When received? (cash flow)
  when: all_shows_settled           // Optional event guard
}

Full specification: clause-type-specification-v1_4.md


Deal Types

A Deal Type is a template that guides deal composition. It suggests which clause types to use together but does not constrain—users can freely add, omit, or modify clauses as long as the resulting deal logic is internally consistent (i.e., the deal can "compile").

Structure

Deal Types contain the following sections.

SectionPurpose
headerIdentity and classification (id, version, name, department, tags)
schemaJSON Schema defining deal-level data structure (parties, dates, territory, currency)
suggested_clausesClause types commonly used with this deal type, with cardinality hints
logicDeal-level events and computations for cross-clause aggregation
outputsAggregated values exposed for reporting and downstream systems

Guiding Principle: Suggest, Don't Dictate

Deal Type: "Music Touring"
├── Suggests: show-settlement clause (required: true)
├── Suggests: tour-versus clause
├── Suggests: travel-reimbursement clause
└── User decides which to include

The required: true flag is advisory only—it pre-selects clauses in the UI and may trigger warnings, but never blocks deal creation. Nonetheless, deals must be internally consistent and any deal lacking an input required by a selected clause would fail validation.

Deal-Level Aggregation

Deal types define logic for aggregating across clauses:

logic {
  computations {
    output total_earned = 
      @show_settlement.total_earned + @bonus.total_earned
    
    output total_pending = total_earned - total_received
  }
}

Full specification: deal-type-specification-v1_3.md


Key DSL Features

for_each Iteration

Process collections with dynamic event naming:

for_each show in shows {
  event {
    name: show_settled_{show.id}
    condition: show.settled == true
  }
  
  computations {
    metric show.earned = max(show.guarantee, show.artist_share)
  }
}

Cross-Clause References

Clauses communicate through declared outputs:

// Single instance
@show_settlement.total_earned

// Multiple instances (cardinality: many)
sum(@bonus_groups[*].earned)

Collection Operations

sum(shows[*].earned) ?? 0
count(shows where show.settled == true)
max(tiers where tier.achieved == true, tier.amount)

Expressions

FeatureSyntax
Null coalescingvalue ?? default
Conditionalif cond then a else b
Arithmeticgross - expenses
Comparisonamount >= threshold

Full DSL reference: dsl-reference-v2_1.md
ANTLR grammar: DealModel-v2.g4


Deal Instances

A Deal Instance is a self-contained, executable representation of a specific contract. Once created, it has no runtime dependencies on the catalog.

Structure: Two Levels of Data

A deal instance contains data and logic at two levels:

mermaid
flowchart TB
    subgraph DI["Deal Instance"]
        DD[Deal Data]
        DL[Deal Logic]
        
        subgraph CI1["Clause Instance A"]
            ID1[Instance Data]
            CL1[Clause Logic]
        end
        
        subgraph CI2["Clause Instance B"]
            ID2[Instance Data]
            CL2[Clause Logic]
        end
        
        subgraph CI3["Clause Instance C"]
            ID3[Instance Data]
            CL3[Clause Logic]
        end
    end
    
    DD --- CI1
    DD --- CI2
    DD --- CI3
    DL --- CI1
    DL --- CI2
    DL --- CI3
LevelDataLogic
Deal InstanceParties, dates, territory, currencyAggregation across clauses, deal-level events
Clause InstanceClause-specific values (shows, tiers, amounts)Copied from clause type, frozen at creation

Self-Containment Principle

When a deal is created, logic is frozen—copied from the clause types and deal type into the instance. Contract terms don't change if types are later updated in the catalog.

mermaid
flowchart LR
    subgraph Catalog["Design-Time Catalog"]
        DT1[Deal Type 1]
        DT2[Deal Type 2]
        
        CTA[Clause Type A]
        CTB[Clause Type B]
        CTC[Clause Type C]
        CTD[Clause Type D]
    end
    
    subgraph Instance["Deal Instance"]
        DD[Deal Data]
        DL[Deal Logic]
        
        CIA[Clause Instance A]
        CIC[Clause Instance C]
        CID[Clause Instance D]
    end
    
    DT1 -.->|suggests| CTA
    DT1 -.->|suggests| CTB
    DT2 ==>|suggests| CTB
    DT2 ==>|suggests| CTC
    DT2 ==>|suggests| CTD
    
    DT2 -->|"schema + logic"| DD
    DT2 -->|"schema + logic"| DL
    CTA -->|"logic copied"| CIA
    CTC -->|"logic copied"| CIC
    CTD -->|"logic copied"| CID
    
    style Instance fill:#e8f5e9

Reactive Computation Model

Deal Engine uses a full-recalculation approach: any data change triggers complete recomputation of all values.

mermaid
flowchart TB
    IC[Input Change] --> FR[Full Recomputation]
    FR --> EC[Evaluate Clauses]
    EC --> ED[Evaluate Deal Logic]
    ED --> NS[New Computed State]
    
    subgraph EC[Evaluate Clauses]
        FE[for_each loops]
        CE[Clause events]
        CO[Clause outputs]
    end

This approach is simpler than incremental computation and guarantees consistent state—there are no stale values or complex dependency tracking.

Full specification: deal-instance-specification-v1_3.md


Instance Versioning

Deal instances are versioned. Every change—whether to data or logic—creates a new immutable version, providing a complete audit trail.

mermaid
flowchart LR
    V1["v1<br/>Initial"] --> V2["v2<br/>Show 1 settled"]
    V2 --> V3["v3<br/>Show 2 settled"]
    V3 --> V4["v4<br/>Bonus amended"]
    V4 --> V5["v5<br/>Show 3 settled"]
    
    style V5 fill:#27ae60,color:white

What Triggers New Versions

Change TypeExampleRecalculation
data_updateSettlement entered, event occurredFull recalculation
clause_additionNew bonus structure addedFull recalculation
clause_replacementRenegotiated termsFull recalculation (new clause only)
logic_amendmentCalculation formula modifiedFull recalculation from inception

Key Versioning Concepts

ConceptDescription
Immutable versionsEach version is a complete, frozen snapshot
Effective datesVersions have effective dates for point-in-time queries
Archived clausesReplaced clauses retain their final computed state
Prior version chainEach version references its predecessor

Effective dates enable backdated amendments (legal changes that apply retroactively) and point-in-time queries ("What did we think this was worth on June 15?").


How Components Relate

mermaid
flowchart TB
    subgraph DesignTime["Design Time"]
        CT1[show-settlement]
        CT2[tour-versus]
        CT3[reimbursement]
        DT[Music Touring Deal Type]
        
        DT -.->|suggests| CT1
        DT -.->|suggests| CT2
        DT -.->|suggests| CT3
    end
    
    subgraph Runtime["Runtime"]
        DI[Deal Instance]
        DI --> DD[deal_data]
        DI --> C1[show_settlement clause]
        DI --> C2[tour_versus clause]
        DI --> CS[computed_state]
    end
    
    CT1 -->|"logic frozen"| C1
    CT2 -->|"logic frozen"| C2
    DT -->|"schema + logic"| DI
    
    style DI fill:#fff3e0

Design Rationale

Why Self-Contained Instances?

Legal contracts shouldn't change unexpectedly. When a deal is created, all logic is copied into the instance. If a clause type is later updated in the catalog, existing deals are unaffected—they contain the logic that was in effect when the contract was made.

Why Suggestions, Not Constraints?

Entertainment contracts are highly variable. Even within the same deal category, contracts differ by artist tier, region, and negotiated terms. Rigid templates would require constant exceptions. Deal types provide guidance while respecting real-world variability.

Why "Deal Must Compile"?

While users have flexibility to add, omit, or modify clauses, the resulting deal must be internally consistent. Cross-clause references must resolve, required fields must be present, and computations must be valid. This constraint ensures that every deal instance is executable.

Why Full Recalculation?

Incremental computation (only recalculating changed values) requires complex dependency tracking and risks stale state. Full recalculation is simpler, always consistent, and easier to audit. The deterministic model means the same inputs always produce the same outputs.

Why Two Classification Dimensions?

Category (guarantee/contingent) and value type (earning/reimbursement/third_party/in_kind) are orthogonal concerns. A guarantee can be an earning (base fee) or a reimbursement (per diem). Both dimensions are needed for accurate commission calculation and accounting treatment.

Why Immutable Versioning?

Every version is preserved as a complete snapshot. This provides a full audit trail, enables point-in-time queries, and meets compliance requirements for financial systems. Storage efficiency is handled at the infrastructure level, not by complicating the versioning model.

Why Explicit Output Interfaces?

Clauses communicate only through declared outputs using @clause.output syntax. This creates clear boundaries between clauses, makes dependencies visible and auditable, and supports clause replacement without breaking references (as long as the output interface is maintained).


Summary

PrincipleImplementation
Separation of concernsDSL defines structure; JSON provides data
ReusabilityClause types compose into deal types
FlexibilityDeal types suggest, don't dictate (within compilation constraints)
Self-containmentInstances have no runtime catalog dependencies
AuditabilityFrozen logic and immutable versions preserve history
Explicit interfacesClauses communicate only through outputs
Dual timingEarned (recognition) and received (cash flow) tracked separately

Confidential. For internal use only.