{
  "contractId": "orisdale-finance-variance-demo",
  "version": "1.0.0",
  "status": "Demonstration rules for a synthetic example. Not a customer-approved policy and not a measured result.",
  "grain": {
    "joinKeys": ["department_id", "period", "currency"],
    "description": "One example department, one period, one currency. Each key combination may appear once per input file."
  },
  "scope": { "period": "2026-09", "currency": "USD" },
  "amounts": {
    "unit": "USD",
    "storage": "Integer cents.",
    "accepted": "Non-negative decimal with at most two decimal places.",
    "rejected": "Negative, non-numeric, empty, or more than two decimal places. Empty is never treated as zero."
  },
  "variance": {
    "formula": "variance_amount = actual_expense - approved_budget",
    "positive": "over budget",
    "negative": "under budget",
    "zero": "on budget"
  },
  "percentage": {
    "formula": "variance_percentage = variance_amount / approved_budget * 100",
    "denominator": "approved_budget",
    "availableWhen": "approved_budget > 0",
    "scale": 4,
    "displayRounding": "Half away from zero at four decimal places.",
    "thresholdComparison": "Exact integer cross-multiplication on unrounded values: |variance_cents| * 100 >= threshold_percent * budget_cents."
  },
  "thresholds": {
    "material": { "absoluteCents": 500000, "percent": 10, "comparison": ">=" },
    "managementAttention": { "absoluteCents": 100000, "percent": 5, "comparison": ">=" }
  },
  "classification": {
    "order": [
      "Material when |variance| >= USD 5,000.00 OR |variance percentage| >= 10%.",
      "Management attention when not Material and |variance| >= USD 1,000.00 OR |variance percentage| >= 5%.",
      "Within tolerance otherwise."
    ],
    "direction": "Classification uses the absolute value. Direction is reported separately."
  },
  "zeroBudget": {
    "percentage": "Unavailable (null). Never infinity and never zero.",
    "category": "Needs human review",
    "reviewReason": "Approved budget is zero, so the variance percentage is unavailable."
  },
  "rejections": {
    "duplicateGrain": "Every row sharing a duplicated key is rejected. No row is silently chosen.",
    "missingRow": "A department present in only one input file is rejected and reported.",
    "invalidOrMissingAmount": "The row is rejected and reported. No value is converted to zero.",
    "outOfScope": "Rows outside the declared period or currency are rejected and reported."
  },
  "reviewStates": ["Pending human review", "Needs human review (rule-based)", "Rejected input"]
}
