{"files":{"main.ts":"import {run} from './core.ts';\nimport {POLICY} from './policy.ts';\nexport function evaluate(payload: any): any { return run(payload, POLICY); }\n","policy.ts":"export const POLICY: any = {\n  scope_key: 'global',\n  latest_by: 'timestamp',\n  tie_policy: 'last',\n  delete_wins: false,\n  allow_resurrection: false,\n  amount_mode: 'delta',\n  precision: 2,\n  gap_policy: 'ignore',\n  audit_duplicate: false,\n  order: 'input',\n  max_age: 120,\n  inclusive_age: false\n};\n","helpers.ts":"export function parseDec(s: string, scale: number): bigint {\n  let str = String(s).trim();\n  let neg = false;\n  if (str.startsWith('-')) { neg = true; str = str.slice(1); } else if (str.startsWith('+')) str = str.slice(1);\n  const parts = str.split('.');\n  const ip = parts[0] || '0';\n  const fp = (parts[1] || '').padEnd(scale, '0');\n  const v = BigInt(ip + fp);\n  return neg ? -v : v;\n}\n\nexport function fracLen(s: string): number {\n  const i = String(s).indexOf('.');\n  return i < 0 ? 0 : String(s).length - i - 1;\n}\n\nexport function fmt(v: bigint, scale: number, prec: number): string {\n  let r: bigint;\n  if (scale <= prec) {\n    r = v * 10n ** BigInt(prec - scale);\n  } else {\n    const d = 10n ** BigInt(scale - prec);\n    let q = v / d;\n    const rem = v % d;\n    if (rem * 2n >= d) q += 1n;\n    r = q;\n  }\n  const neg = r < 0n;\n  if (neg) r = -r;\n  let s = r.toString();\n  if (prec > 0) {\n    s = s.padStart(prec + 1, '0');\n    s = s.slice(0, s.length - prec) + '.' + s.slice(s.length - prec);\n  }\n  return (neg ? '-' : '') + s;\n}\n","core.ts":"import {parseDec, fracLen, fmt} from './helpers.ts';\n\nexport function run(payload: any, policy: any): any {\n  const now = payload.now;\n  const events: any[] = payload.events || [];\n  let scale = policy.precision;\n  for (const e of events) scale = Math.max(scale, fracLen(e.amount));\n\n  const kept: {e: any, idx: number}[] = [];\n  for (let i = 0; i < events.length; i++) {\n    const e = events[i];\n    const age = now - e.ts;\n    if (age > policy.max_age) continue;\n    if (age === policy.max_age && !policy.inclusive_age) continue;\n    kept.push({e, idx: i});\n  }\n\n  const seen = new Set<string>();\n  const duplicates: any[] = [];\n  const uniq: {e: any, idx: number}[] = [];\n  for (const k of kept) {\n    const key = policy.scope_key === 'tenant' ? JSON.stringify([k.e.tenant, k.e.id]) : JSON.stringify(k.e.id);\n    if (seen.has(key)) {\n      if (policy.audit_duplicate) duplicates.push(k.e.id);\n      continue;\n    }\n    seen.add(key);\n    uniq.push(k);\n  }\n\n  const groups = new Map<string, {tenant: any, entity: any, items: {e: any, idx: number}[], first: number}>();\n  for (const k of uniq) {\n    const key = JSON.stringify([k.e.tenant, k.e.entity]);\n    let g = groups.get(key);\n    if (!g) { g = {tenant: k.e.tenant, entity: k.e.entity, items: [], first: k.idx}; groups.set(key, g); }\n    g.items.push(k);\n  }\n\n  const field = policy.latest_by === 'timestamp' ? 'ts' : 'seq';\n  const out: any[] = [];\n  const gl = Array.from(groups.values());\n  for (const g of gl) {\n    // tie filtering\n    const byVal = new Map<number, any>();\n    for (const k of g.items) {\n      const v = k.e[field];\n      if (!byVal.has(v) || policy.tie_policy === 'last') byVal.set(v, k.e);\n    }\n    const retained = Array.from(byVal.entries()).sort((a, b) => a[0] - b[0]).map(x => x[1]);\n    let seq = 0;\n    let value = 0n;\n    let deleted = false;\n    for (const e of retained) {\n      if (policy.gap_policy === 'ignore' && e.seq !== seq + 1) continue;\n      seq = e.seq;\n      if (e.kind === 'delete') {\n        deleted = true;\n      } else {\n        if (!deleted || policy.allow_resurrection) {\n          deleted = false;\n          const a = parseDec(e.amount, scale);\n          value = policy.amount_mode === 'absolute' ? a : value + a;\n        }\n      }\n    }\n    if (policy.delete_wins && retained.some(e => e.kind === 'delete')) deleted = true;\n    out.push({tenant: g.tenant, entity: g.entity, value: fmt(value, scale, policy.precision), deleted, first: g.first});\n  }\n\n  if (policy.order === 'key') {\n    const cmp = (a: any, b: any) => (a < b ? -1 : a > b ? 1 : 0);\n    out.sort((a, b) => cmp(a.tenant, b.tenant) || cmp(a.entity, b.entity));\n  } else {\n    out.sort((a, b) => a.first - b.first);\n  }\n  return {\n    entities: out.map(o => ({tenant: o.tenant, entity: o.entity, value: o.value, deleted: o.deleted})),\n    duplicates\n  };\n}\n"}}