{"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: any = payload ? payload.now : 0;\n  const inputEvents: any[] = payload && Array.isArray(payload.events) ? payload.events : [];\n  const maxAge: number = policy.max_age;\n  const inclusiveAge: boolean = !!policy.inclusive_age;\n  const duplicates: any[] = [];\n  const seen: Set<string> = new Set<string>();\n  const retained: any[] = [];\n  for (let i = 0; i < inputEvents.length; i++) {\n    const ev: any = inputEvents[i];\n    const age: number = now - ev.ts;\n    if (age > maxAge || (!inclusiveAge && age === maxAge)) continue;\n    const dedupKey: string = policy.scope_key === 'tenant' ? String(ev.tenant) + '\\u0000' + String(ev.id) : String(ev.id);\n    if (seen.has(dedupKey)) {\n      if (policy.audit_duplicate) duplicates.push(ev.id);\n      continue;\n    }\n    seen.add(dedupKey);\n    retained.push({id: ev.id, tenant: ev.tenant, entity: ev.entity, seq: ev.seq, ts: ev.ts, kind: ev.kind, amount: ev.amount, _idx: i});\n  }\n  const groups: Map<string, any> = new Map<string, any>();\n  for (const ev of retained) {\n    const gk: string = String(ev.tenant) + '\\u0000' + String(ev.entity);\n    let g: any = groups.get(gk);\n    if (!g) {\n      g = {tenant: ev.tenant, entity: ev.entity, events: [], earliest: ev._idx};\n      groups.set(gk, g);\n    }\n    g.events.push(ev);\n    if (ev._idx < g.earliest) g.earliest = ev._idx;\n  }\n  const sortField: string = policy.latest_by === 'ts' || policy.latest_by === 'time' || policy.latest_by === 'timestamp' ? 'ts' : 'seq';\n  const results: any[] = [];\n  for (const g of groups.values()) {\n    const byTie: Map<string, any> = new Map<string, any>();\n    for (const ev of g.events) {\n      const tk: string = String(ev[sortField]);\n      if (!byTie.has(tk)) byTie.set(tk, ev);\n      else if (policy.tie_policy === 'last') byTie.set(tk, ev);\n    }\n    const kept: any[] = Array.from(byTie.values());\n    const sorted: any[] = kept.slice().sort((a: any, b: any) => {\n      const av: number = a[sortField];\n      const bv: number = b[sortField];\n      if (av < bv) return -1;\n      if (av > bv) return 1;\n      return a._idx - b._idx;\n    });\n    let processedSeq: number = 0;\n    let value: any = {units: 0n, scale: 0};\n    let deleted: boolean = false;\n    let hasDelete: boolean = false;\n    for (const ev of sorted) if (ev.kind === 'delete') hasDelete = true;\n    for (const ev of sorted) {\n      if (policy.gap_policy === 'ignore' && ev.seq !== processedSeq + 1) continue;\n      processedSeq = ev.seq;\n      if (ev.kind === 'delete') {\n        deleted = true;\n      } else if (ev.kind === 'set') {\n        if (!deleted || policy.allow_resurrection) {\n          deleted = false;\n          const amt: any = parseDecimal(ev.amount === undefined || ev.amount === null ? '0' : String(ev.amount));\n          if (policy.amount_mode === 'delta') value = addDecimal(value, amt);\n          else value = amt;\n        }\n      }\n    }\n    if (policy.delete_wins && hasDelete) deleted = true;\n    results.push({tenant: g.tenant, entity: g.entity, value: formatDecimal(value, policy.precision), deleted: deleted, _earliest: g.earliest});\n  }\n  if (policy.order === 'key') {\n    results.sort((a: any, b: any) => {\n      const at: string = String(a.tenant);\n      const bt: string = String(b.tenant);\n      if (at < bt) return -1;\n      if (at > bt) return 1;\n      const ae: string = String(a.entity);\n      const be: string = String(b.entity);\n      if (ae < be) return -1;\n      if (ae > be) return 1;\n      return 0;\n    });\n  } else {\n    results.sort((a: any, b: any) => a._earliest - b._earliest);\n  }\n  const entities: any[] = results.map((r: any) => ({tenant: r.tenant, entity: r.entity, value: r.value, deleted: r.deleted}));\n  return {entities: entities, duplicates: duplicates};\n}\n", "policy.ts": "export const POLICY: any = {\"allow_resurrection\": true, \"amount_mode\": \"absolute\", \"audit_duplicate\": true, \"delete_wins\": true, \"gap_policy\": \"accept\", \"inclusive_age\": true, \"latest_by\": \"sequence\", \"max_age\": 60, \"order\": \"key\", \"precision\": 0, \"scope_key\": \"tenant\", \"tie_policy\": \"first\"};\n", "helpers.ts": "export function parseDecimal(input: string): any {\n  let s: string = String(input).trim();\n  let negative: boolean = false;\n  if (s.startsWith('-')) { negative = true; s = s.slice(1); }\n  else if (s.startsWith('+')) s = s.slice(1);\n  const dot: number = s.indexOf('.');\n  let intPart: string = dot === -1 ? s : s.slice(0, dot);\n  const fracPart: string = dot === -1 ? '' : s.slice(dot + 1);\n  if (intPart === '') intPart = '0';\n  const combined: string = intPart + fracPart;\n  let units: bigint = combined === '' ? 0n : BigInt(combined);\n  if (negative) units = -units;\n  return {units: units, scale: fracPart.length};\n}\nexport function addDecimal(a: any, b: any): any {\n  if (a.scale === b.scale) return {units: a.units + b.units, scale: a.scale};\n  if (a.scale < b.scale) {\n    const diff: bigint = 10n ** BigInt(b.scale - a.scale);\n    return {units: a.units * diff + b.units, scale: b.scale};\n  }\n  const diff: bigint = 10n ** BigInt(a.scale - b.scale);\n  return {units: a.units + b.units * diff, scale: a.scale};\n}\nexport function formatDecimal(value: any, precision: number): string {\n  let units: bigint = value.units;\n  const scale: number = value.scale;\n  const negative: boolean = units < 0n;\n  if (negative) units = -units;\n  if (scale > precision) {\n    const divisor: bigint = 10n ** BigInt(scale - precision);\n    const q: bigint = units / divisor;\n    const r: bigint = units % divisor;\n    units = r * 2n >= divisor ? q + 1n : q;\n  } else if (scale < precision) {\n    units = units * (10n ** BigInt(precision - scale));\n  }\n  let digits: string = units.toString();\n  let out: string;\n  if (precision === 0) out = digits;\n  else {\n    digits = digits.padStart(precision + 1, '0');\n    out = digits.slice(0, digits.length - precision) + '.' + digits.slice(digits.length - precision);\n  }\n  return negative && units !== 0n ? '-' + out : out;\n}\n"}}