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:
- How much does talent get paid?
- When is that earned?
- 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)
}
}| Field | Purpose | Example |
|---|---|---|
amount | How much talent gets paid | base_fee_total, sum(shows[*].earned), net_receipts |
earned | When that value is earned (accounting) | Straight-line over term, on milestone, on settlement |
received | When cash is received (cash flow) | 60 days after execution, quarterly installments |
when | Event guard for activation | contract_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 Field | Draws From |
|---|---|
amount: net_receipts | Computation: output net_receipts = gross - fees - costs |
amount: sum(shows[*].earned) | For_each populates show.earned, then aggregated |
earned: on show_settlement_schedule | Schedule triggered by settlement events |
received: on quarterly_receipts | Schedule defining quarterly cash receipt timing |
when: adjusted_gross_positive | Event: 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)
| Category | Description | Forecasting |
|---|---|---|
guarantee | Certain payment when conditions met | Committed |
contingent | Conditional on event occurrence | Possible |
simple | Non-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
| Category | Value Type | Example |
|---|---|---|
| guarantee | earning | Base fee |
| guarantee | reimbursement | Per diem |
| guarantee | third_party | Publicist fee |
| guarantee | in_kind | Wardrobe allowance |
| contingent | earning | Performance bonus |
| contingent | reimbursement | Additional travel if services extended |
| contingent | third_party | Additional stylist if awards show |
| contingent | in_kind | Extra wardrobe if option exercised |
| simple | (none) | Exclusivity terms, territory rights |
2.3 Requirements by Value Type
| Value Type | amount | earned | received | Additional |
|---|---|---|---|---|
earning | Required | Required | Required | — |
reimbursement | Required | Not used | Required | — |
third_party | Required | Not used | Required | payee required in schema |
in_kind | Optional | Optional | Optional | Flexible 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"
}| Field | Required | Description |
|---|---|---|
id | Yes | Unique identifier (kebab-case) |
version | Yes | Semantic version (e.g., 1.0.0) |
category | Yes | guarantee, contingent, or simple |
value_type | Financial only | earning, reimbursement, third_party, or in_kind |
name | Yes | Human-readable name |
description | Yes | Brief 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
outputssection 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
varinsidelogicare local to this clause - Variables can reference fields from the clause's schema directly
- Deal-level data is accessed via the
inputssection - Cross-clause data is accessed via
@clause_name.outputsyntax ininputs
Null coalescing operator:
expr ?? defaultreturnsexprif not null, otherwisedefault- 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
}| Field | Required | Description |
|---|---|---|
amount | Yes | The financial value (references output or computation) |
earned | Required for earning | Schedule defining when revenue is recognized |
received | Yes (except in_kind) | Schedule defining when cash is received |
when | Optional | Event guard for clause activation |
The on keyword references a schedule defined in the schema:
earned: on earning_schedule→ uses theearning_schedulefrom schemareceived: on receipt_schedule→ uses thereceipt_schedulefrom 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_namesyntax
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):
| Pattern | Description | Example |
|---|---|---|
straight_line | Linear accrual over period | Base fee earned evenly over 3-year term |
event_triggered | Earned when event occurs | Bonus earned when milestone achieved |
periodic | Earned in regular periods | Monthly earning during production |
In schema:
{
"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):
{
"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):
| Pattern | Description | Example |
|---|---|---|
equal_periodic_installments | Equal amounts at regular intervals | Quarterly payments |
event_installments | Specific amounts at events | 50/25/25 split |
In schema:
{
"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:
{
"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
| Rule | Description |
|---|---|
| CT-1 | id must be unique across catalog |
| CT-2 | version must be valid semver |
| CT-3 | category must be: guarantee, contingent, or simple |
| CT-4 | Financial clauses (guarantee/contingent) must have value_type |
| CT-5 | Simple clauses must not have value_type |
| CT-6 | Financial clauses must have financial section |
| CT-7 | Simple clauses must not have financial section |
6.2 Financial Section Validation
| Rule | Description |
|---|---|
| FN-1 | amount required for all financial clauses |
| FN-2 | earned required for earning value_type |
| FN-3 | received required for earning, reimbursement, third_party |
| FN-4 | amount must reference a valid output or computation |
| FN-5 | earned must reference a valid schedule in schema |
| FN-6 | received must reference a valid schedule in schema |
| FN-7 | when (if present) must reference a valid event |
6.3 Value Type Specific Validation
| Rule | Description |
|---|---|
| VT-1 | earning must have earning_schedule in schema |
| VT-2 | third_party must have payee in schema |
| VT-3 | in_kind may optionally have value tracking |
| VT-4 | reimbursement must not have earned field |
6.4 Logic Validation
| Rule | Description |
|---|---|
| LV-1 | Variables declared with var are local to clause |
| LV-2 | No circular dependencies in computations |
| LV-3 | Event conditions must evaluate to boolean |
| LV-4 | for_each collections must exist in schema |
| LV-5 | Outputs must be populated in computations |
| LV-6 | Cross-clause references (@clause.output) must target declared outputs |
6.5 Expression Operators
| Operator | Description | Example |
|---|---|---|
?? | Null coalescing | sum(values) ?? 0 |
&& | Logical AND | a && b |
| ` | ` | |
! | Logical NOT | !condition |
==, != | Equality | status == "complete" |
<, <=, >, >= | Comparison | amount >= threshold |
+, -, *, / | Arithmetic | gross - 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 Term | v1.3 Term | Rationale |
|---|---|---|
kind | category | Avoids overuse of "type" |
type (for value nature) | value_type | More specific |
schedule (in clause) | earned | Clarifies purpose (revenue recognition) |
payable | received | Clarifies purpose (cash receipt) |
by_schedule | on | Simpler 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
clausetofinancial - Changed
schedule/payabletoearned/receivedfor clarity - Changed
by_schedulekeyword toon - Documented
@clause_name.outputsyntax for cross-clause references - Added
??null coalescing operator - Clarified local variable scoping in
logicsection - Eliminated
on_settlementpattern (useevent_triggeredinstead) - Added Section 8 documenting terminology changes from v2.7
- Renamed nested section from
- 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
clausesection 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