{"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, formatRounded} from './helpers.ts';\nimport type {DecimalValue} from './helpers.ts';\nexport function run(payload: any, policy: any): any {\n  const now: number = payload.now;\n  const inputEvents: any[] = Array.isArray(payload.events) ? payload.events : [];\n  const duplicates: string[] = [];\n  type Item = {event: any; index: number};\n  const aged: Item[] = [];\n  for (let i = 0; i < inputEvents.length; i++) {\n    const event: any = inputEvents[i];\n    const age: number = now - event.ts;\n    if (age > policy.max_age) continue;\n    if (!policy.inclusive_age && age === policy.max_age) continue;\n    aged.push({event, index: i});\n  }\n  const seen: Set<string> = new Set<string>();\n  const deduped: Item[] = [];\n  for (const item of aged) {\n    const key: string = policy.scope_key === 'tenant' ? item.event.tenant + '\\u0000' + item.event.id : item.event.id;\n    if (seen.has(key)) {\n      if (policy.audit_duplicate) duplicates.push(item.event.id);\n      continue;\n    }\n    seen.add(key);\n    deduped.push(item);\n  }\n  type Group = {tenant: string; entity: string; items: Item[]};\n  const groups: Map<string, Group> = new Map<string, Group>();\n  for (const item of deduped) {\n    const key: string = item.event.tenant + '\\u0000' + item.event.entity;\n    let group: Group | undefined = groups.get(key);\n    if (group === undefined) {\n      group = {tenant: item.event.tenant, entity: item.event.entity, items: []};\n      groups.set(key, group);\n    }\n    group.items.push(item);\n  }\n  const sortField: string = policy.latest_by === 'sequence' || policy.latest_by === 'seq' ? 'seq' : 'ts';\n  type Result = {tenant: string; entity: string; value: string; deleted: boolean; earliest: number};\n  const results: Result[] = [];\n  for (const group of groups.values()) {\n    let earliest: number = group.items.length > 0 ? group.items[0].index : 0;\n    for (const item of group.items) {\n      if (item.index < earliest) earliest = item.index;\n    }\n    const byTie: Map<number, Item> = new Map<number, Item>();\n    for (const item of group.items) {\n      const tieKey: number = item.event[sortField];\n      if (!byTie.has(tieKey)) {\n        byTie.set(tieKey, item);\n      } else if (policy.tie_policy === 'last') {\n        byTie.set(tieKey, item);\n      }\n    }\n    const retained: Item[] = Array.from(byTie.values());\n    const sorted: Item[] = retained.slice().sort((a: Item, b: Item) => {\n      const av: number = a.event[sortField];\n      const bv: number = b.event[sortField];\n      if (av < bv) return -1;\n      if (av > bv) return 1;\n      return 0;\n    });\n    const hasDelete: boolean = retained.some((item: Item) => item.event.kind === 'delete');\n    let currentSeq: number = 0;\n    let value: DecimalValue = {units: BigInt(0), scale: 0};\n    let deleted: boolean = false;\n    for (const item of sorted) {\n      const event: any = item.event;\n      if (policy.gap_policy === 'ignore' && event.seq !== currentSeq + 1) continue;\n      currentSeq = event.seq;\n      if (event.kind === 'delete') {\n        deleted = true;\n      } else if (event.kind === 'set') {\n        if (!deleted || policy.allow_resurrection) {\n          deleted = false;\n          const amount: DecimalValue = parseDecimal(event.amount);\n          if (policy.amount_mode === 'delta') value = addDecimal(value, amount);\n          else value = amount;\n        }\n      }\n    }\n    if (policy.delete_wins && hasDelete) deleted = true;\n    results.push({tenant: group.tenant, entity: group.entity, value: formatRounded(value, policy.precision), deleted, earliest});\n  }\n  if (policy.order === 'key') {\n    results.sort((a: Result, b: Result) => {\n      if (a.tenant < b.tenant) return -1;\n      if (a.tenant > b.tenant) return 1;\n      if (a.entity < b.entity) return -1;\n      if (a.entity > b.entity) return 1;\n      return 0;\n    });\n  } else {\n    results.sort((a: Result, b: Result) => a.earliest - b.earliest);\n  }\n  const entities: any[] = results.map((r: Result) => ({tenant: r.tenant, entity: r.entity, value: r.value, deleted: r.deleted}));\n  return {entities, 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 type DecimalValue = {units: bigint; scale: number};\nfunction pow10(n: number): bigint {\n  let result: bigint = BigInt(1);\n  for (let i = 0; i < n; i++) result = result * BigInt(10);\n  return result;\n}\nexport function parseDecimal(text: string): DecimalValue {\n  const s: string = String(text).trim();\n  const dot: number = s.indexOf('.');\n  if (dot < 0) return {units: BigInt(s === '' ? '0' : s), scale: 0};\n  const intPart: string = s.slice(0, dot);\n  const fracPart: string = s.slice(dot + 1);\n  const digits: string = (intPart === '' ? '0' : intPart) + fracPart;\n  return {units: BigInt(digits === '' ? '0' : digits), scale: fracPart.length};\n}\nexport function addDecimal(a: DecimalValue, b: DecimalValue): DecimalValue {\n  const scale: number = Math.max(a.scale, b.scale);\n  const av: bigint = a.units * pow10(scale - a.scale);\n  const bv: bigint = b.units * pow10(scale - b.scale);\n  return {units: av + bv, scale};\n}\nexport function formatRounded(value: DecimalValue, precision: number): string {\n  let scaled: bigint;\n  if (value.scale <= precision) {\n    scaled = value.units * pow10(precision - value.scale);\n  } else {\n    const divisor: bigint = pow10(value.scale - precision);\n    const quotient: bigint = value.units / divisor;\n    const remainder: bigint = value.units % divisor;\n    scaled = remainder * BigInt(2) >= divisor ? quotient + BigInt(1) : quotient;\n  }\n  const digitsRaw: string = scaled.toString();\n  if (precision === 0) return digitsRaw;\n  const padded: string = digitsRaw.padStart(precision + 1, '0');\n  return padded.slice(0, padded.length - precision) + '.' + padded.slice(padded.length - precision);\n}\n"}}