{"files": {"main.ts": "import {run} from './core.ts';\nimport {POLICY} from './policy.ts';\nexport function evaluate(payload: any): any { return run(payload, POLICY); }\n", "core.ts": "import { parseDecimal, addDecimal, formatDecimal } from './helpers.ts';\nexport function run(payload: any, policy: any): any {\n  const now = payload ? payload.now : 0;\n  const inputEvents: any[] = payload && Array.isArray(payload.events) ? payload.events : [];\n  const maxAge = policy.max_age;\n  const inclusiveAge = !!policy.inclusive_age;\n  const auditDuplicate = !!policy.audit_duplicate;\n  const scopeTenant = policy.scope_key === 'tenant';\n  const duplicates: any[] = [];\n  const seen = new Set<string>();\n  type Entry = { ev: any; idx: number };\n  const kept: Entry[] = [];\n  for (let i = 0; i < inputEvents.length; i++) {\n    const ev = inputEvents[i];\n    const age = now - ev.ts;\n    if (maxAge !== undefined && maxAge !== null) {\n      if (age > maxAge) continue;\n      if (age === maxAge && !inclusiveAge) continue;\n    }\n    const dupKey = scopeTenant ? String(ev.tenant) + '\\u0000' + String(ev.id) : String(ev.id);\n    if (seen.has(dupKey)) {\n      if (auditDuplicate) duplicates.push(ev.id);\n      continue;\n    }\n    seen.add(dupKey);\n    kept.push({ ev, idx: i });\n  }\n  type Group = { tenant: any; entity: any; entries: Entry[]; earliest: number };\n  const groups = new Map<string, Group>();\n  for (const entry of kept) {\n    const ev = entry.ev;\n    const key = String(ev.tenant) + '\\u0000' + String(ev.entity);\n    let g = groups.get(key);\n    if (!g) { g = { tenant: ev.tenant, entity: ev.entity, entries: [], earliest: entry.idx }; groups.set(key, g); }\n    g.entries.push(entry);\n    if (entry.idx < g.earliest) g.earliest = entry.idx;\n  }\n  const useTs = policy.latest_by === 'timestamp' || policy.latest_by === 'ts';\n  const sortField = useTs ? 'ts' : 'seq';\n  const tieLast = policy.tie_policy === 'last';\n  const gapIgnore = policy.gap_policy === 'ignore';\n  const allowResurrection = !!policy.allow_resurrection;\n  const deleteWins = !!policy.delete_wins;\n  const amountMode = policy.amount_mode;\n  const precision = typeof policy.precision === 'number' ? policy.precision : 0;\n  type Out = { tenant: any; entity: any; value: string; deleted: boolean; earliest: number };\n  const out: Out[] = [];\n  for (const g of groups.values()) {\n    const byKey = new Map<any, Entry>();\n    for (const entry of g.entries) {\n      const k = entry.ev[sortField];\n      if (!byKey.has(k)) byKey.set(k, entry);\n      else if (tieLast) byKey.set(k, entry);\n    }\n    const retained: Entry[] = Array.from(byKey.values());\n    const sorted = retained.slice().sort((a, b) => {\n      const av = a.ev[sortField]; const bv = b.ev[sortField];\n      return av < bv ? -1 : av > bv ? 1 : 0;\n    });\n    let seq = 0;\n    let valueUnits = BigInt(0);\n    let valueScale = 0;\n    let deleted = false;\n    const hasDelete = retained.some((e) => e.ev.kind === 'delete');\n    for (const entry of sorted) {\n      const ev = entry.ev;\n      if (gapIgnore && ev.seq !== seq + 1) continue;\n      if (ev.kind === 'delete') {\n        deleted = true;\n      } else if (ev.kind === 'set') {\n        if (!deleted || allowResurrection) {\n          deleted = false;\n          const amt = parseDecimal(ev.amount !== undefined && ev.amount !== null ? String(ev.amount) : '0');\n          if (amountMode === 'delta') {\n            const r = addDecimal(valueUnits, valueScale, amt.units, amt.scale);\n            valueUnits = r.units; valueScale = r.scale;\n          } else {\n            valueUnits = amt.units; valueScale = amt.scale;\n          }\n        }\n      }\n      seq = ev.seq;\n    }\n    if (deleteWins && hasDelete) deleted = true;\n    out.push({ tenant: g.tenant, entity: g.entity, value: formatDecimal(valueUnits, valueScale, precision), deleted, earliest: g.earliest });\n  }\n  let entities: any[];\n  if (policy.order === 'key') {\n    entities = out.slice().sort((a, b) => {\n      if (String(a.tenant) < String(b.tenant)) return -1;\n      if (String(a.tenant) > String(b.tenant)) return 1;\n      if (String(a.entity) < String(b.entity)) return -1;\n      if (String(a.entity) > String(b.entity)) return 1;\n      return 0;\n    }).map((e) => ({ tenant: e.tenant, entity: e.entity, value: e.value, deleted: e.deleted }));\n  } else {\n    entities = out.slice().sort((a, b) => a.earliest - b.earliest).map((e) => ({ tenant: e.tenant, entity: e.entity, value: e.value, deleted: e.deleted }));\n  }\n  return { entities, duplicates };\n}\n", "policy.ts": "export const POLICY: any = {\"delete_wins\": true, \"latest_by\": \"sequence\", \"scope_key\": \"tenant\", \"tie_policy\": \"first\", \"allow_resurrection\": true, \"amount_mode\": \"absolute\", \"gap_policy\": \"accept\", \"precision\": 0, \"inclusive_age\": true, \"max_age\": 60, \"audit_duplicate\": true, \"order\": \"key\"};\n", "helpers.ts": "export function pow10(n: number): bigint { let r = BigInt(1); const ten = BigInt(10); for (let i = 0; i < n; i++) r = r * ten; return r; }\nexport function parseDecimal(s: string): { units: bigint; scale: number } {\n  let t = String(s).trim();\n  let neg = false;\n  if (t.startsWith('-')) { neg = true; t = t.slice(1); }\n  if (t.startsWith('+')) t = t.slice(1);\n  const parts = t.split('.');\n  const intPart = parts[0] === '' ? '0' : parts[0];\n  const fracPart = parts.length > 1 ? parts[1] : '';\n  const digits = (intPart + fracPart).replace(/^0+(?=\\d)/, '');\n  let units = BigInt(digits === '' ? '0' : digits);\n  if (neg) units = -units;\n  return { units, scale: fracPart.length };\n}\nexport function addDecimal(aUnits: bigint, aScale: number, bUnits: bigint, bScale: number): { units: bigint; scale: number } {\n  const scale = Math.max(aScale, bScale);\n  const a = aUnits * pow10(scale - aScale);\n  const b = bUnits * pow10(scale - bScale);\n  return { units: a + b, scale };\n}\nexport function formatDecimal(units: bigint, scale: number, precision: number): string {\n  let neg = units < BigInt(0);\n  let u = neg ? -units : units;\n  if (scale > precision) {\n    const div = pow10(scale - precision);\n    const q = u / div;\n    const r = u % div;\n    const rounded = r * BigInt(2) >= div ? q + BigInt(1) : q;\n    u = rounded;\n  } else if (scale < precision) {\n    u = u * pow10(precision - scale);\n  }\n  if (u === BigInt(0)) neg = false;\n  let s = u.toString();\n  if (precision === 0) return neg ? '-' + s : s;\n  if (s.length <= precision) s = '0'.repeat(precision - s.length + 1) + s;\n  const intPart = s.slice(0, s.length - precision);\n  const fracPart = s.slice(s.length - precision);\n  const out = intPart + '.' + fracPart;\n  return neg ? '-' + out : out;\n}\n"}}