Skip to content

Clause Type Specification v1.4

Document Purpose: Define the complete structure, semantics, and usage of Clause Types in the Deal Engine architecture revision.

Status: Draft for review

Version: 1.4 - Refined terminology and structure based on review


1. Overview

1.1 What is a Clause Type?

A Clause Type is a reusable, self-contained unit that defines a specific kind of contractual term. For financial clauses, it answers three fundamental questions:

  1. How much does talent get paid?
  2. When is that earned?
  3. When is that received?

Clause Types are design-time artifacts stored in a catalog. When a deal is created, the relevant clause type's schema and logic are copied into the deal instance, creating an independent snapshot.

1.2 The Core of a Financial Clause

Every financial clause has this essential structure:

clause_type {
  ...
  financial {
    amount: base_fee_total                    // HOW MUCH
    earned: on base_fee_earning               // WHEN EARNED (revenue recognition)
    received: on base_fee_receipts            // WHEN RECEIVED (cash flow)
    when: contract_executed                   // IF (optional event guard)
  }
}
FieldPurposeExample
amountHow much talent gets paidbase_fee_total, sum(shows[*].earned), net_receipts
earnedWhen that value is earned (accounting)Straight-line over term, on milestone, on settlement
receivedWhen cash is received (cash flow)60 days after execution, quarterly installments
whenEvent guard for activationcontract_executed, milestone_achieved

1.3 How Logic Connects to the Core

The clause's logic elements (events, computations, for_each) all feed into the financial structure:

┌─────────────────────────────────────────────────────────────┐
│                        CLAUSE LOGIC                          │
├─────────────────────────────────────────────────────────────┤
│  events          →  Define conditions (when/if things happen)│
│  for_each        →  Iterate over collections (shows, tiers)  │
│  computations    →  Calculate derived values                 │
└────────────────────────────┬────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                    FINANCIAL STRUCTURE                       │
├─────────────────────────────────────────────────────────────┤
│  amount   ← populated by computations, aggregations          │
│  earned   ← references schedules for revenue recognition     │
│  received ← references schedules for cash receipt timing     │
│  when     ← references events for activation                 │
└─────────────────────────────────────────────────────────────┘

Examples of connections:

Financial FieldDraws From
amount: net_receiptsComputation: output net_receipts = gross - fees - costs
amount: sum(shows[*].earned)For_each populates show.earned, then aggregated
earned: on show_settlement_scheduleSchedule triggered by settlement events
received: on quarterly_receiptsSchedule defining quarterly cash receipt timing
when: adjusted_gross_positiveEvent: clause only activates when AGP > 0

2. Clause Classification

2.1 Two Orthogonal Dimensions

Every clause is classified along two independent dimensions:

Dimension 1: Category (Certainty of obligation)

CategoryDescriptionForecasting
guaranteeCertain payment when conditions metCommitted
contingentConditional on event occurrencePossible
simpleNon-financial terms (text only)N/A

Dimension 2: Value Type (Nature of value) — Financial clauses only

| Value Type | Description | Accounting | |------------|-------------|----------------|------------| | earning | Earned income | Revenue recognition | | reimbursement | Expense pass-through | Expense treatment | | third_party | Payment to service provider | Different payee | | in_kind | Non-cash benefit | Separate tracking |

2.2 Valid Combinations

CategoryValue TypeExample
guaranteeearningBase fee
guaranteereimbursementPer diem
guaranteethird_partyPublicist fee
guaranteein_kindWardrobe allowance
contingentearningPerformance bonus
contingentreimbursementAdditional travel if services extended
contingentthird_partyAdditional stylist if awards show
contingentin_kindExtra wardrobe if option exercised
simple(none)Exclusivity terms, territory rights

2.3 Requirements by Value Type

Value TypeamountearnedreceivedAdditional
earningRequiredRequiredRequired
reimbursementRequiredNot usedRequired
third_partyRequiredNot usedRequiredpayee required in schema
in_kindOptionalOptionalOptionalFlexible value tracking

Note: earned is required for earning value_type because earnings require revenue recognition timing for accounting purposes. Reimbursements and third-party payments don't have earning schedules—they're not the talent's revenue.


3. Clause Type Structure

A clause type consists of these sections:

clause_type {
  header { ... }      // Identity and classification
  schema { ... }      // JSON Schema for clause data
  inputs { ... }      // Deal-level data this clause needs
  logic { ... }       // Events, for_each, computations
  financial { ... }   // The core financial structure (financial clauses only)
  outputs { ... }     // Values exposed to deal level and other clauses
  template { ... }    // Contract text rendering
}

3.1 Header Section

header {
  id: show-settlement
  version: 1.0.0
  category: guarantee
  value_type: earning
  name: "Show Settlement"
  description: "Per-show guarantee vs percentage with settlement"
}
FieldRequiredDescription
idYesUnique identifier (kebab-case)
versionYesSemantic version (e.g., 1.0.0)
categoryYesguarantee, contingent, or simple
value_typeFinancial onlyearning, reimbursement, third_party, or in_kind
nameYesHuman-readable name
descriptionYesBrief description of purpose

3.2 Schema Section

Defines the JSON Schema for data this clause operates on.

schema {
  type: object
  required: [shows, artist_percentage]
  properties {
    shows {
      type: array
      items {
        type: object
        properties {
          id { type: string }
          date { type: string, format: date }
          venue { type: string }
          guarantee { type: number }
          gross_revenue { type: number }
          expenses { type: number }
          settled { type: boolean }
          // Computed fields (populated by logic)
          artist_share { type: [number, null] }
          earned { type: [number, null] }
        }
      }
    }
    artist_percentage { type: number }
    earning_schedule { ... }
    receipt_schedule { ... }
  }
}

Schedule definitions in schema:

Schedules are defined in the schema using the canonical patterns from the schedule specifications:

earning_schedule {
  type: object
  properties {
    pattern { type: string, enum: ["straight_line", "event_triggered", "periodic"] }
    // Pattern-specific fields...
  }
}

receipt_schedule {
  type: object
  properties {
    pattern { type: string, enum: ["equal_periodic_installments", "event_installments"] }
    // Pattern-specific fields...
  }
}

3.3 Inputs Section

Declares deal-level data this clause needs access to.

inputs {
  effective_date: deal.dates.effective_date
  currency: deal.currency
  talent_name: deal.parties.talent.name
  
  // Cross-clause references (only declared outputs)
  tour_guarantee: @tour_terms.total_guarantee
}

Cross-clause references use the @clause_name.output_name syntax:

  • The @ prefix indicates a reference to another clause instance
  • Only values declared in the referenced clause's outputs section are accessible
  • This enforces explicit interfaces between clauses

3.4 Logic Section

Contains events, iterations, computations, and local variables that feed the financial structure.

logic {
  // Local variables (clause-scoped)
  var settlement_threshold = 1000
  
  // Iterate over shows
  for_each show in shows {
    
    // Events for this show
    event {
      name: show_occurred_{show.id}
      condition: show.date <= today
    }
    
    event {
      name: show_settled_{show.id}
      condition: show.settled == true
    }
    
    // Computations for this show
    computations {
      metric show.artist_share = (show.gross_revenue - show.expenses) * artist_percentage
      metric show.earned = max(show.guarantee, show.artist_share ?? 0)
    }
  }
  
  // Clause-level events
  event {
    name: all_shows_settled
    condition: count(shows where show.settled == true) == count(shows)
  }
  
  // Clause-level computations
  computations {
    output total_guarantees = sum(shows[*].guarantee)
    output total_earned = sum(shows[*].earned) ?? 0
  }
}

Variable scoping rules:

  • Variables declared with var inside logic are local to this clause
  • Variables can reference fields from the clause's schema directly
  • Deal-level data is accessed via the inputs section
  • Cross-clause data is accessed via @clause_name.output syntax in inputs

Null coalescing operator:

  • expr ?? default returns expr if not null, otherwise default
  • Useful when aggregating computed fields that may be null

3.5 Financial Section (Financial Clauses Only)

The financial section defines the clause's financial interface—what it produces.

financial {
  amount: total_earned
  earned: on earning_schedule
  received: on receipt_schedule
  when: all_shows_settled
}
FieldRequiredDescription
amountYesThe financial value (references output or computation)
earnedRequired for earningSchedule defining when revenue is recognized
receivedYes (except in_kind)Schedule defining when cash is received
whenOptionalEvent guard for clause activation

The on keyword references a schedule defined in the schema:

  • earned: on earning_schedule → uses the earning_schedule from schema
  • received: on receipt_schedule → uses the receipt_schedule from schema

Simple clauses (category: simple) do not have a financial section.

3.6 Outputs Section

Declares values exposed to deal-level logic and other clauses.

outputs {
  total_guarantees: number
  total_earned: number
  total_artist_share: number
  all_shows_occurred: boolean
  all_shows_settled: boolean
}

Important: Only values declared in outputs can be referenced by:

  • Deal-level computations
  • Other clauses via @clause_name.output_name syntax

This creates explicit, auditable interfaces between clauses.

3.7 Template Section

Contract text with access to all clause data and computations.

template {
  """
  PERFORMANCE COMPENSATION
  
  For each performance, Artist shall receive the greater of:
  (a) A guarantee of the amount specified per show, or
  (b) {{ percent(artist_percentage) }} of net revenues
  
  Shows:
  {{ for show in shows }}
  - {{ show.venue }} ({{ date(show.date) }}): 
    Guarantee: {{ money(show.guarantee, currency) }}
    {{ if show.settled }}Earned: {{ money(show.earned, currency) }}{{ end }}
  {{ end }}
  
  Total Earned: {{ money(total_earned, currency) }}
  """
}

4. Schedule Specifications

4.1 Earning Schedule (Required for earning value_type)

Earning schedules define when revenue accrues for accounting/revenue recognition.

Canonical patterns (from schedule-patterns-spec):

PatternDescriptionExample
straight_lineLinear accrual over periodBase fee earned evenly over 3-year term
event_triggeredEarned when event occursBonus earned when milestone achieved
periodicEarned in regular periodsMonthly earning during production

In schema:

json
{
  "earning_schedule": {
    "pattern": "straight_line",
    "start_date": "{{effective_date}}",
    "end_date": "{{term_end}}",
    "description": "Earned evenly over contract term"
  }
}

For per-item earning (e.g., per-show):

json
{
  "earning_schedule": {
    "pattern": "event_triggered",
    "event": "show_settled_{show.id}",
    "description": "Earned upon show settlement"
  }
}

In financial section:

financial {
  amount: total_earned
  earned: on earning_schedule
  ...
}

4.2 Receipt Schedule

Receipt schedules define when cash is received from the buyer.

Canonical patterns (from receipt-schedule-patterns-spec):

PatternDescriptionExample
equal_periodic_installmentsEqual amounts at regular intervalsQuarterly payments
event_installmentsSpecific amounts at events50/25/25 split

In schema:

json
{
  "receipt_schedule": {
    "pattern": "event_installments",
    "total_amount": 300000,
    "installments": [
      { "percentage": 50, "event": "contract_executed", "days_after": 60 },
      { "percentage": 50, "event": "work_completed", "days_after": 60 }
    ]
  }
}

In financial section:

financial {
  amount: total_earned
  received: on receipt_schedule
  ...
}

4.3 Events in Schedules

Schedules reference events defined in the logic section:

logic {
  event {
    name: contract_executed
    condition: contract_executed_flag == true
  }
  
  event {
    name: work_completed
    condition: all_deliverables_complete == true
  }
}

Then in receipt_schedule JSON:

json
{
  "installments": [
    { "event": "contract_executed", "days_after": 60 },
    { "event": "work_completed", "days_after": 60 }
  ]
}

5. Complete Examples

5.1 Show Settlement (guarantee / earning)

Per-show guarantee vs percentage with tour-level aggregation.

clause_type {
  header {
    id: show-settlement
    version: 1.0.0
    category: guarantee
    value_type: earning
    name: "Show Settlement"
    description: "Per-show guarantee vs percentage calculation"
  }
  
  schema {
    type: object
    required: [shows, artist_percentage, earning_schedule, receipt_schedule]
    properties {
      shows {
        type: array
        items {
          type: object
          required: [id, date, venue, guarantee]
          properties {
            id { type: string }
            date { type: string, format: date }
            venue { type: string }
            guarantee { type: number }
            gross_revenue { type: [number, null] }
            expenses { type: [number, null] }
            occurred { type: boolean, default: false }
            settled { type: boolean, default: false }
            settlement_date { type: [string, null], format: date }
            // Computed
            artist_share { type: [number, null] }
            earned { type: [number, null] }
          }
        }
      }
      artist_percentage { type: number, minimum: 0, maximum: 1 }
      earning_schedule {
        type: object
        properties {
          pattern { type: string, enum: ["event_triggered"] }
          event { type: string }
        }
      }
      receipt_schedule {
        type: object
        properties {
          pattern { type: string, enum: ["event_installments"] }
          days_after { type: integer, default: 30 }
        }
      }
    }
  }
  
  inputs {
    currency: deal.currency
    talent_name: deal.parties.talent.name
  }
  
  logic {
    for_each show in shows {
      event {
        name: show_occurred_{show.id}
        condition: show.occurred == true
      }
      
      event {
        name: show_settled_{show.id}
        condition: show.settled == true
      }
      
      computations {
        metric show.artist_share = 
          if show.gross_revenue != null && show.expenses != null then
            (show.gross_revenue - show.expenses) * artist_percentage
          else null
        
        metric show.earned = 
          if show.settled then
            max(show.guarantee, show.artist_share ?? 0)
          else if show.occurred then
            show.guarantee  // Minimum guaranteed
          else null
      }
    }
    
    event {
      name: any_shows_occurred
      condition: count(shows where show.occurred == true) > 0
    }
    
    event {
      name: all_shows_occurred
      condition: count(shows where show.occurred == true) == count(shows)
    }
    
    event {
      name: all_shows_settled
      condition: count(shows where show.settled == true) == count(shows)
    }
    
    computations {
      output total_guarantees = sum(shows[*].guarantee)
      output total_artist_share = sum(shows[*].artist_share) ?? 0
      output total_earned = sum(shows[*].earned) ?? 0
      output shows_occurred = count(shows where show.occurred == true)
      output shows_settled = count(shows where show.settled == true)
      output total_shows = count(shows)
    }
  }
  
  financial {
    amount: total_earned
    earned: on earning_schedule
    received: on receipt_schedule
    when: any_shows_occurred
  }
  
  outputs {
    total_guarantees: number
    total_artist_share: number
    total_earned: number
    shows_occurred: number
    shows_settled: number
    total_shows: number
    any_shows_occurred: boolean
    all_shows_occurred: boolean
    all_shows_settled: boolean
  }
  
  template {
    """
    SHOW COMPENSATION
    
    {{ talent_name }} shall receive for each show the greater of:
    (a) The guaranteed amount, or
    (b) {{ percent(artist_percentage) }} of net box office receipts
    
    {{ for show in shows }}
    {{ show.venue }} - {{ date(show.date) }}
      Guarantee: {{ money(show.guarantee, currency) }}
      {{ if show.settled }}
      Net Receipts: {{ money(show.gross_revenue - show.expenses, currency) }}
      Artist Share: {{ money(show.artist_share, currency) }}
      EARNED: {{ money(show.earned, currency) }}
      {{ else if show.occurred }}
      Status: Occurred, pending settlement
      {{ else }}
      Status: Scheduled
      {{ end }}
    {{ end }}
    
    TOTAL GUARANTEES: {{ money(total_guarantees, currency) }}
    TOTAL EARNED: {{ money(total_earned, currency) }}
    """
  }
}

5.2 Tiered Bonus (contingent / earning)

Bonus groups with achievement tiers and selection rules.

clause_type {
  header {
    id: tiered-bonus
    version: 1.0.0
    category: contingent
    value_type: earning
    name: "Tiered Bonus Structure"
    description: "Bonus groups with achievement tiers and selection rules"
  }
  
  schema {
    type: object
    required: [bonus_groups, earning_schedule, receipt_schedule]
    properties {
      bonus_groups {
        type: array
        items {
          type: object
          required: [id, name, selection, tiers]
          properties {
            id { type: string }
            name { type: string }
            selection { type: string, enum: ["highest", "highest_plus_cumulative", "sum"] }
            eligible { type: boolean, default: false }
            tiers {
              type: array
              items {
                type: object
                properties {
                  id { type: string }
                  description { type: string }
                  amount { type: number }
                  achieved { type: boolean, default: false }
                  cumulative { type: boolean, default: false }
                }
              }
            }
            // Computed
            earned { type: [number, null] }
          }
        }
      }
      earning_schedule {
        type: object
        properties {
          pattern { type: string, enum: ["event_triggered"] }
          event { type: string }
        }
      }
      receipt_schedule {
        type: object
        properties {
          pattern { type: string }
          days_after_achievement { type: integer }
        }
      }
    }
  }
  
  inputs {
    currency: deal.currency
    talent_name: deal.parties.talent.name
  }
  
  logic {
    for_each group in bonus_groups {
      event {
        name: group_eligible_{group.id}
        condition: group.eligible == true
      }
      
      for_each tier in group.tiers {
        event {
          name: tier_achieved_{group.id}_{tier.id}
          condition: tier.achieved == true
        }
      }
      
      computations {
        metric group.earned = 
          if !group.eligible then 0
          else if group.selection == "highest" then
            max(group.tiers where tier.achieved == true, tier.amount) ?? 0
          else if group.selection == "highest_plus_cumulative" then
            (max(group.tiers where tier.achieved == true && tier.cumulative == false, tier.amount) ?? 0) +
            sum(group.tiers where tier.achieved == true && tier.cumulative == true, tier.amount)
          else if group.selection == "sum" then
            sum(group.tiers where tier.achieved == true, tier.amount)
          else 0
      }
    }
    
    event {
      name: any_bonus_earned
      condition: sum(bonus_groups[*].earned) > 0
    }
    
    computations {
      output total_earned = sum(bonus_groups[*].earned)
      output total_potential = sum(bonus_groups[*].tiers[*].amount)
      output groups_with_earnings = count(bonus_groups where group.earned > 0)
    }
  }
  
  financial {
    amount: total_earned
    earned: on earning_schedule
    received: on receipt_schedule
    when: any_bonus_earned
  }
  
  outputs {
    total_earned: number
    total_potential: number
    groups_with_earnings: number
    any_bonus_earned: boolean
  }
  
  template {
    """
    PERFORMANCE BONUSES
    
    {{ talent_name }} shall be eligible for the following bonuses:
    
    {{ for group in bonus_groups }}
    {{ group.name }} ({{ group.selection }}):
    {{ for tier in group.tiers }}
      - {{ tier.description }}: {{ money(tier.amount, currency) }}
        {{ if tier.achieved }}✓ ACHIEVED{{ end }}
        {{ if tier.cumulative }}(cumulative){{ end }}
    {{ end }}
    {{ if group.earned > 0 }}GROUP EARNED: {{ money(group.earned, currency) }}{{ end }}
    {{ end }}
    
    TOTAL POTENTIAL: {{ money(total_potential, currency) }}
    TOTAL EARNED: {{ money(total_earned, currency) }}
    """
  }
}

5.3 Expense Reimbursement (guarantee / reimbursement)

Pass-through expenses.

clause_type {
  header {
    id: expense-reimbursement
    version: 1.0.0
    category: guarantee
    value_type: reimbursement
    name: "Expense Reimbursement"
    description: "Pass-through expenses"
  }
  
  schema {
    type: object
    required: [expense_categories]
    properties {
      expense_categories {
        type: array
        items {
          type: object
          required: [id, name, budgeted_amount]
          properties {
            id { type: string }
            name { type: string }
            budgeted_amount { type: number }
            cap { type: [number, null] }
            actual_amount { type: [number, null] }
            approved { type: boolean, default: false }
            paid { type: boolean, default: false }
            // Computed
            reimbursable { type: [number, null] }
          }
        }
      }
      receipt_schedule {
        type: object
        properties {
          pattern { type: string, default: "event_installments" }
          days_after { type: integer, default: 30 }
        }
      }
    }
  }
  
  inputs {
    currency: deal.currency
  }
  
  logic {
    for_each category in expense_categories {
      event {
        name: expense_approved_{category.id}
        condition: category.approved == true
      }
      
      event {
        name: expense_paid_{category.id}
        condition: category.paid == true
      }
      
      computations {
        metric category.reimbursable = 
          if category.actual_amount == null then null
          else if category.cap != null then min(category.actual_amount, category.cap)
          else category.actual_amount
      }
    }
    
    event {
      name: any_expenses_approved
      condition: count(expense_categories where category.approved == true) > 0
    }
    
    computations {
      output total_budgeted = sum(expense_categories[*].budgeted_amount)
      output total_reimbursable = sum(expense_categories[*].reimbursable) ?? 0
      output total_approved = sum(expense_categories where category.approved == true, category.reimbursable) ?? 0
      output total_paid = sum(expense_categories where category.paid == true, category.reimbursable) ?? 0
    }
  }
  
  financial {
    amount: total_approved
    // No 'earned' - reimbursements don't have revenue recognition
    received: on receipt_schedule
    when: any_expenses_approved
  }
  
  outputs {
    total_budgeted: number
    total_reimbursable: number
    total_approved: number
    total_paid: number
    any_expenses_approved: boolean
  }
  
  template {
    """
    EXPENSE REIMBURSEMENT
    
    The following expenses shall be reimbursed:
    
    {{ for category in expense_categories }}
    {{ category.name }}:
      Budget: {{ money(category.budgeted_amount, currency) }}
      {{ if category.cap }}Cap: {{ money(category.cap, currency) }}{{ end }}
      {{ if category.actual_amount }}Actual: {{ money(category.actual_amount, currency) }}{{ end }}
      {{ if category.approved }}APPROVED: {{ money(category.reimbursable, currency) }}{{ end }}
    {{ end }}
    
    Total Approved: {{ money(total_approved, currency) }}
    """
  }
}

5.4 Service Provider Fee (guarantee / third_party)

Payment to third party, requires payee.

clause_type {
  header {
    id: service-provider-fee
    version: 1.0.0
    category: guarantee
    value_type: third_party
    name: "Service Provider Fee"
    description: "Payment to third-party service provider"
  }
  
  schema {
    type: object
    required: [payee, service_description, fee_amount]
    properties {
      payee {
        type: object
        required: [name]
        properties {
          name { type: string }
          entity { type: string }
          contact { type: string }
          payment_instructions { type: string }
        }
      }
      service_description { type: string }
      service_type { type: string, enum: ["stylist", "publicist", "trainer", "photographer", "other"] }
      fee_amount { type: number }
      fee_structure { type: string, enum: ["flat", "per_day", "per_event"], default: "flat" }
      quantity { type: integer, default: 1 }
      service_rendered { type: boolean, default: false }
      paid { type: boolean, default: false }
      payment_date { type: [string, null], format: date }
      receipt_schedule {
        type: object
        properties {
          pattern { type: string }
          trigger_event { type: string }
          days_after { type: integer }
        }
      }
    }
  }
  
  inputs {
    currency: deal.currency
    buyer_name: deal.parties.buyer.name
  }
  
  logic {
    var total_fee = fee_amount * quantity
    
    event {
      name: service_rendered
      condition: service_rendered == true
    }
    
    event {
      name: payment_made
      condition: paid == true
    }
    
    computations {
      output total_amount = total_fee
      output amount_paid = if paid then total_fee else 0
      output amount_outstanding = if paid then 0 else total_fee
    }
  }
  
  financial {
    amount: total_amount
    // No 'earned' - this isn't talent's revenue
    received: on receipt_schedule
    when: service_rendered
  }
  
  outputs {
    total_amount: number
    amount_paid: number
    amount_outstanding: number
    service_rendered: boolean
    payment_made: boolean
  }
  
  template {
    """
    THIRD-PARTY SERVICE PROVIDER
    
    {{ buyer_name }} shall pay directly to:
    
    Provider: {{ payee.name }}
    {{ if payee.entity }}Entity: {{ payee.entity }}{{ end }}
    Service: {{ service_description }}
    
    Fee: {{ money(fee_amount, currency) }} ({{ fee_structure }})
    {{ if quantity > 1 }}Quantity: {{ quantity }}{{ end }}
    Total: {{ money(total_amount, currency) }}
    
    Status: {{ if paid }}PAID{{ else }}PENDING{{ end }}
    """
  }
}

5.5 Product Allowance (guarantee / in_kind)

Non-cash benefit with optional value tracking.

clause_type {
  header {
    id: product-allowance
    version: 1.0.0
    category: guarantee
    value_type: in_kind
    name: "Product/Service Allowance"
    description: "Non-cash benefit (wardrobe, products, services)"
  }
  
  schema {
    type: object
    required: [benefit_type, benefit_description]
    properties {
      benefit_type { type: string, enum: ["wardrobe", "travel", "accommodation", "product", "service", "discount", "other"] }
      benefit_description { type: string }
      
      // Optional value tracking - flexible format
      estimated_value {
        type: object
        properties {
          amount { type: [number, null] }
          period { type: string, enum: ["total", "annual", "monthly", "per_use"] }
          currency { type: string }
          calculation_notes { type: string }
        }
      }
      
      // Alternative: discount-based
      discount_value {
        type: object
        properties {
          discount_percentage { type: number }
          retail_value { type: [number, null] }
        }
      }
      
      availability {
        type: object
        properties {
          start_date { type: string, format: date }
          end_date { type: [string, null], format: date }
        }
      }
      
      utilized { type: boolean, default: false }
    }
  }
  
  inputs {
    talent_name: deal.parties.talent.name
    buyer_name: deal.parties.buyer.name
  }
  
  logic {
    event {
      name: benefit_utilized
      condition: utilized == true
    }
    
    computations {
      metric tracked_value = 
        if estimated_value.amount != null then estimated_value.amount
        else if discount_value.retail_value != null && discount_value.discount_percentage != null then
          discount_value.retail_value * discount_value.discount_percentage
        else null
      
      output estimated_total_value = tracked_value
      output is_utilized = utilized
    }
  }
  
  financial {
    amount: estimated_total_value    // May be null if not tracked
    // No schedules required for in_kind
  }
  
  outputs {
    estimated_total_value: number    // May be null
    is_utilized: boolean
  }
  
  template {
    """
    IN-KIND BENEFIT
    
    {{ buyer_name }} shall provide {{ talent_name }} with:
    
    Type: {{ benefit_type }}
    Description: {{ benefit_description }}
    
    {{ if estimated_value.amount }}
    Estimated Value: {{ money(estimated_value.amount, estimated_value.currency) }} ({{ estimated_value.period }})
    {{ end }}
    
    {{ if discount_value.discount_percentage }}
    Discount: {{ percent(discount_value.discount_percentage) }} off retail
    {{ end }}
    
    Status: {{ if utilized }}UTILIZED{{ else }}AVAILABLE{{ end }}
    """
  }
}

5.6 Exclusivity (simple)

Non-financial terms, text only.

clause_type {
  header {
    id: exclusivity
    version: 1.0.0
    category: simple
    // No value_type for simple clauses
    name: "Exclusivity Terms"
    description: "Non-compete and category exclusivity"
  }
  
  schema {
    type: object
    required: [category, competitors, duration]
    properties {
      category { type: string }
      competitors { type: array, items: { type: string } }
      duration { type: string }
      exceptions { type: array, items: { type: string } }
      geographic_scope { type: string }
    }
  }
  
  inputs {
    talent_name: deal.parties.talent.name
    brand_name: deal.parties.buyer.brand_name
  }
  
  logic {
    // Simple clauses have minimal or no logic
  }
  
  // No financial section - simple clauses have no financial structure
  
  outputs {
    // Simple clauses typically have no outputs
  }
  
  template {
    """
    EXCLUSIVITY
    
    During {{ duration }}, {{ talent_name }} shall not render services
    for products in the {{ category }} category competing with {{ brand_name }},
    including:
    
    {{ for competitor in competitors }}
    - {{ competitor }}
    {{ end }}
    
    {{ if exceptions }}
    Exceptions:
    {{ for exception in exceptions }}
    - {{ exception }}
    {{ end }}
    {{ end }}
    """
  }
}

6. Validation Rules

6.1 Structure Validation

RuleDescription
CT-1id must be unique across catalog
CT-2version must be valid semver
CT-3category must be: guarantee, contingent, or simple
CT-4Financial clauses (guarantee/contingent) must have value_type
CT-5Simple clauses must not have value_type
CT-6Financial clauses must have financial section
CT-7Simple clauses must not have financial section

6.2 Financial Section Validation

RuleDescription
FN-1amount required for all financial clauses
FN-2earned required for earning value_type
FN-3received required for earning, reimbursement, third_party
FN-4amount must reference a valid output or computation
FN-5earned must reference a valid schedule in schema
FN-6received must reference a valid schedule in schema
FN-7when (if present) must reference a valid event

6.3 Value Type Specific Validation

RuleDescription
VT-1earning must have earning_schedule in schema
VT-2third_party must have payee in schema
VT-3in_kind may optionally have value tracking
VT-4reimbursement must not have earned field

6.4 Logic Validation

RuleDescription
LV-1Variables declared with var are local to clause
LV-2No circular dependencies in computations
LV-3Event conditions must evaluate to boolean
LV-4for_each collections must exist in schema
LV-5Outputs must be populated in computations
LV-6Cross-clause references (@clause.output) must target declared outputs

6.5 Expression Operators

OperatorDescriptionExample
??Null coalescingsum(values) ?? 0
&&Logical ANDa && b
``
!Logical NOT!condition
==, !=Equalitystatus == "complete"
<, <=, >, >=Comparisonamount >= threshold
+, -, *, /Arithmeticgross - expenses

7. Design Rationale

7.1 Why Lead with Financial Structure?

The essence of a financial clause is: how much, when earned, when received. Everything else (events, computations, for_each) exists to populate these core fields. Leading with this structure makes the purpose clear.

7.2 Why Separate financial Section?

The financial section explicitly shows the financial interface—what the clause ultimately produces. It's the contract between the clause's internal logic and the outside world.

7.3 Why earned and received?

These terms directly answer the two business questions:

  • earned: When is revenue recognized? (accounting concept)
  • received: When is cash received? (cash flow concept)

Using schedule and payable was ambiguous. The new terms make the purpose explicit.

7.4 Why Two Classification Dimensions?

category and value_type are orthogonal:

  • A guarantee can be an earning (base fee) or reimbursement (per diem)
  • A contingent can be an earning (bonus) or third_party (conditional stylist)

Both dimensions are needed for accurate aggregation, commission calculation, and accounting treatment.

7.5 Why Cross-Clause References via Outputs Only?

The @clause_name.output syntax only allows access to declared outputs. This:

  • Creates explicit interfaces between clauses
  • Prevents tight coupling to internal implementation details
  • Makes dependencies auditable
  • Supports clause type versioning (outputs are the stable interface)
  • Output interface stability supports clause replacement without breaking references

7.6 Why Null Coalescing (??)?

When aggregating computed fields that may be null (e.g., shows not yet settled), we need a clean way to provide defaults. sum(shows[*].earned) ?? 0 is more readable than a verbose if-then-else.


8. Terminology Changes from v2.7

This specification uses updated terminology from the original design decisions document:

v2.7 Termv1.3 TermRationale
kindcategoryAvoids overuse of "type"
type (for value nature)value_typeMore specific
schedule (in clause)earnedClarifies purpose (revenue recognition)
payablereceivedClarifies purpose (cash receipt)
by_scheduleonSimpler syntax

Document History

  • v1.4 (2026-01-12) - Added versioning comments
    • Removed mentions of "commissionable" amounts
  • v1.3 (2026-01-XX) - Refined terminology and structure
    • Renamed nested section from clause to financial
    • Changed schedule/payable to earned/received for clarity
    • Changed by_schedule keyword to on
    • Documented @clause_name.output syntax for cross-clause references
    • Added ?? null coalescing operator
    • Clarified local variable scoping in logic section
    • Eliminated on_settlement pattern (use event_triggered instead)
    • Added Section 8 documenting terminology changes from v2.7
  • v1.2 (2026-01-XX) - Restructured around core financial structure
    • Added Section 1.2 defining the core: amount, schedule, payable, when
    • Added Section 1.3 showing how logic connects to core
    • Added explicit clause section to clause type structure
    • Reorganized examples to show clause section prominently
    • Updated validation rules for clause section
  • v1.1 (2026-01-XX) - Added two-dimensional classification
  • v1.0 (2026-01-XX) - Initial specification

Confidential. For internal use only.