{"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 = {\"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 type Dec = {n: bigint, s: number};\nexport function parseDec(str: string): Dec {\n  const t = String(str).trim();\n  const parts = t.split('.');\n  const ip = parts[0] || '0';\n  const fp = parts[1] || '';\n  return {n: BigInt(ip + fp), s: fp.length};\n}\nexport function addDec(a: Dec, b: Dec): Dec {\n  const s = Math.max(a.s, b.s);\n  const x = a.n * (10n ** BigInt(s - a.s));\n  const y = b.n * (10n ** BigInt(s - b.s));\n  return {n: x + y, s};\n}\nexport function fmtDec(d: Dec, p: number): string {\n  let q: bigint;\n  if (d.s <= p) {\n    q = d.n * (10n ** BigInt(p - d.s));\n  } else {\n    const div = 10n ** BigInt(d.s - p);\n    q = d.n / div;\n    const r = d.n % div;\n    if (r * 2n >= div) q += 1n;\n  }\n  let str = q.toString();\n  if (p === 0) return str;\n  while (str.length <= p) str = '0' + str;\n  return str.slice(0, str.length - p) + '.' + str.slice(str.length - p);\n}\nexport function cmp(a: string, b: string): number {\n  return a < b ? -1 : a > b ? 1 : 0;\n}\n","core.ts":"import {parseDec, addDec, fmtDec, cmp, Dec} 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 === 'ts' ? 'ts' : 'seq';\n  const retained: {e: any, i: number}[] = [];\n  events.forEach((e, i) => {\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, i});\n  });\n  const seen = new Set<string>();\n  const duplicates: string[] = [];\n  const kept: {e: any, i: 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: string, entity: string, items: {e: any, i: 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: {g: any, first: number, ent: any}[] = [];\n  for (const g of groups.values()) {\n    const first = g.items[0].i;\n    const sorted = g.items.slice().sort((a, b) => a.e[field] - b.e[field]);\n    const filtered: any[] = [];\n    for (const r of sorted) {\n      const last = filtered.length ? filtered[filtered.length - 1] : null;\n      if (last && last[field] === r.e[field]) {\n        if (policy.tie_policy === 'last') filtered[filtered.length - 1] = r.e;\n      } else {\n        filtered.push(r.e);\n      }\n    }\n    let seq = 0;\n    let value: Dec = {n: 0n, s: 0};\n    let deleted = false;\n    let anyDelete = false;\n    for (const e of filtered) {\n      if (e.kind === 'delete') anyDelete = true;\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({g, first, ent: {tenant: g.tenant, entity: g.entity, value: fmtDec(value, policy.precision), deleted}});\n  }\n  if (policy.order === 'key') {\n    out.sort((a, b) => cmp(a.g.tenant, b.g.tenant) || cmp(a.g.entity, b.g.entity));\n  } else {\n    out.sort((a, b) => a.first - b.first);\n  }\n  return {entities: out.map(o => o.ent), duplicates};\n}\n"}}