{"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  delete_wins: false,\n  latest_by: 'timestamp',\n  scope_key: 'global',\n  tie_policy: 'last',\n  allow_resurrection: false,\n  amount_mode: 'delta',\n  gap_policy: 'ignore',\n  precision: 2,\n  audit_duplicate: false,\n  order: 'input',\n  inclusive_age: false,\n  max_age: 120\n};\n","helpers.ts":"export function parseDec(s: string): {n: bigint, scale: number} {\n  let str = String(s).trim();\n  const i = str.indexOf('.');\n  if (i < 0) return {n: BigInt(str), scale: 0};\n  const frac = str.slice(i + 1);\n  return {n: BigInt(str.slice(0, i) + frac), scale: frac.length};\n}\n\nexport function addDec(a: {n: bigint, scale: number}, b: {n: bigint, scale: number}) {\n  const sc = Math.max(a.scale, b.scale);\n  const x = a.n * 10n ** BigInt(sc - a.scale);\n  const y = b.n * 10n ** BigInt(sc - b.scale);\n  return {n: x + y, scale: sc};\n}\n\nexport function fmtDec(v: {n: bigint, scale: number}, p: number): string {\n  let q: bigint;\n  if (v.scale <= p) {\n    q = v.n * 10n ** BigInt(p - v.scale);\n  } else {\n    const d = 10n ** BigInt(v.scale - p);\n    q = v.n / d;\n    const r = v.n % d;\n    if (r * 2n >= d) q += 1n;\n  }\n  if (p === 0) return q.toString();\n  let s = q.toString();\n  while (s.length < p + 1) s = '0' + s;\n  return s.slice(0, s.length - p) + '.' + s.slice(s.length - p);\n}\n","core.ts":"import {parseDec, addDec, fmtDec} from './helpers.ts';\n\nexport function run(payload: any, policy: any): any {\n  const now = payload.now;\n  const events: any[] = payload.events || [];\n  const field = (policy.latest_by === 'seq') ? 'seq' : 'ts';\n  const retained: {e: any, idx: number}[] = [];\n  events.forEach((e, idx) => {\n    const age = now - e.ts;\n    if (age > policy.max_age) return;\n    if (age === policy.max_age && !policy.inclusive_age) return;\n    retained.push({e, idx});\n  });\n  const seen = new Set<string>();\n  const duplicates: any[] = [];\n  const kept: {e: any, idx: number}[] = [];\n  for (const r of retained) {\n    const key = policy.scope_key === 'tenant' ? JSON.stringify([r.e.tenant, r.e.id]) : JSON.stringify(r.e.id);\n    if (seen.has(key)) {\n      if (policy.audit_duplicate) duplicates.push(r.e.id);\n      continue;\n    }\n    seen.add(key);\n    kept.push(r);\n  }\n  const groups = new Map<string, {tenant: any, entity: any, items: {e: any, idx: number}[]}>();\n  for (const r of kept) {\n    const k = JSON.stringify([r.e.tenant, r.e.entity]);\n    let g = groups.get(k);\n    if (!g) { g = {tenant: r.e.tenant, entity: r.e.entity, items: []}; groups.set(k, g); }\n    g.items.push(r);\n  }\n  const out: any[] = [];\n  for (const g of groups.values()) {\n    const earliest = g.items[0].idx;\n    const sorted = g.items.map((x, i) => ({x, i})).sort((a, b) => {\n      const d = a.x.e[field] - b.x.e[field];\n      return d !== 0 ? d : a.i - b.i;\n    }).map(o => o.x);\n    const filtered: {e: any, idx: number}[] = [];\n    for (const r of sorted) {\n      const last = filtered[filtered.length - 1];\n      if (last && last.e[field] === r.e[field]) {\n        if (policy.tie_policy === 'last') filtered[filtered.length - 1] = r;\n      } else filtered.push(r);\n    }\n    let seq = 0;\n    let value = {n: 0n, scale: 0};\n    let deleted = false;\n    let anyDelete = false;\n    for (const r of g.items) if (r.e.kind === 'delete') anyDelete = true;\n    for (const r of filtered) {\n      const e = r.e;\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 amt = parseDec(e.amount);\n          value = policy.amount_mode === 'delta' ? addDec(value, amt) : amt;\n        }\n      }\n    }\n    if (policy.delete_wins && anyDelete) deleted = true;\n    out.push({tenant: g.tenant, entity: g.entity, value: fmtDec(value, policy.precision), deleted, _i: earliest});\n  }\n  if (policy.order === 'key') {\n    out.sort((a, b) => {\n      if (a.tenant !== b.tenant) return a.tenant < b.tenant ? -1 : 1;\n      if (a.entity !== b.entity) return a.entity < b.entity ? -1 : 1;\n      return 0;\n    });\n  } else {\n    out.sort((a, b) => a._i - b._i);\n  }\n  const entities = out.map(o => ({tenant: o.tenant, entity: o.entity, value: o.value, deleted: o.deleted}));\n  return {entities, duplicates};\n}\n"}}