{"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\": \"seq\", \"max_age\": 60, \"order\": \"key\", \"precision\": 0, \"scope_key\": \"tenant\", \"tie_policy\": \"first\"};\n","helpers.ts":"export function parseDec(s: string): {n: bigint, sc: number} {\n  const t = String(s).trim();\n  const i = t.indexOf('.');\n  if (i < 0) return {n: BigInt(t || '0'), sc: 0};\n  const frac = t.slice(i + 1);\n  const ip = t.slice(0, i) || '0';\n  return {n: BigInt(ip + frac), sc: frac.length};\n}\nexport function pow10(k: number): bigint { return 10n ** BigInt(k); }\nexport function fmt(n: bigint, sc: number, p: number): string {\n  let q: bigint;\n  if (sc > p) {\n    const d = pow10(sc - p);\n    q = n / d;\n    const r = n % d;\n    if (r * 2n >= d) q += 1n;\n  } else {\n    q = n * pow10(p - sc);\n  }\n  let s = q.toString();\n  if (p === 0) return s;\n  while (s.length <= p) s = '0' + s;\n  return s.slice(0, s.length - p) + '.' + s.slice(s.length - p);\n}\n","core.ts":"import {parseDec, pow10, 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  const sortField = policy.latest_by === 'ts' ? 'ts' : 'seq';\n  const aged: any[] = [];\n  for (const e of events) {\n    const age = now - e.ts;\n    if (age > policy.max_age) continue;\n    if (age === policy.max_age && !policy.inclusive_age) continue;\n    aged.push(e);\n  }\n  const seen = new Set<string>();\n  const duplicates: string[] = [];\n  const kept: {e: any, idx: number}[] = [];\n  aged.forEach((e, idx) => {\n    const key = policy.scope_key === 'tenant' ? JSON.stringify([e.tenant, e.id]) : JSON.stringify([e.id]);\n    if (seen.has(key)) {\n      if (policy.audit_duplicate) duplicates.push(e.id);\n      return;\n    }\n    seen.add(key);\n    kept.push({e, idx});\n  });\n  const groups = new Map<string, {tenant: string, entity: string, items: {e: any, idx: number}[]}>();\n  for (const k of kept) {\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: []}; groups.set(key, g); }\n    g.items.push(k);\n  }\n  let S = policy.precision;\n  for (const k of kept) { const d = parseDec(k.e.amount); if (d.sc > S) S = d.sc; }\n  const out: {g: any, first: number, rec: any}[] = [];\n  for (const g of groups.values()) {\n    const first = g.items[0].idx;\n    const byVal = new Map<number, {e: any, idx: number}[]>();\n    for (const it of g.items) {\n      const v = it.e[sortField];\n      if (!byVal.has(v)) byVal.set(v, []);\n      byVal.get(v)!.push(it);\n    }\n    const retained: any[] = [];\n    for (const [, arr] of byVal) {\n      retained.push(policy.tie_policy === 'last' ? arr[arr.length - 1].e : arr[0].e);\n    }\n    retained.sort((a, b) => a[sortField] - b[sortField]);\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 if (e.kind === 'set') {\n        if (!deleted || policy.allow_resurrection) {\n          deleted = false;\n          const d = parseDec(e.amount);\n          const sc = d.n * pow10(S - d.sc);\n          if (policy.amount_mode === 'delta') value += sc; else value = sc;\n        }\n      }\n    }\n    if (policy.delete_wins && retained.some(e => e.kind === 'delete')) deleted = true;\n    out.push({g, first, rec: {tenant: g.tenant, entity: g.entity, value: fmt(value, S, policy.precision), deleted}});\n  }\n  if (policy.order === 'key') {\n    out.sort((a, b) => {\n      if (a.g.tenant !== b.g.tenant) return a.g.tenant < b.g.tenant ? -1 : 1;\n      if (a.g.entity !== b.g.entity) return a.g.entity < b.g.entity ? -1 : 1;\n      return 0;\n    });\n  } else {\n    out.sort((a, b) => a.first - b.first);\n  }\n  return {entities: out.map(o => o.rec), duplicates};\n}\n"}}