{
  "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 {deduplicate, retryDelay, compare} from './helpers.ts';\nimport type {IndexedJob} from './helpers.ts';\n\nexport function run(payload: any, policy: any): any {\n  const ready: IndexedJob[] = [];\n  const waiting: {id: string; at: number; index: number}[] = [];\n  const dead: IndexedJob[] = [];\n  const cancelled: IndexedJob[] = [];\n  const now = payload.now;\n\n  for (const entry of deduplicate(payload.jobs, policy.dedup_key)) {\n    const job = entry.job;\n    const retryable = policy.retryable_codes.includes(job.last_code);\n    if (job.cancelled && (policy.cancel_wins || !retryable)) {\n      cancelled.push(entry);\n      continue;\n    }\n    const age = now - job.created;\n    const stale = policy.stale_inclusive\n      ? age >= policy.stale_after\n      : age > policy.stale_after;\n    if (stale || job.attempt >= policy.max_attempts || (job.last_code !== 0 && !retryable)) {\n      dead.push(entry);\n      continue;\n    }\n    const due = retryable\n      ? Math.max(job.due, job.failed_at + retryDelay(job.attempt, policy))\n      : job.due;\n    if (due > now) {\n      waiting.push({id: job.id, at: due, index: entry.index});\n    } else {\n      ready.push(entry);\n    }\n  }\n\n  ready.sort((a, b) => {\n    const priority = compare(a.job.priority, b.job.priority);\n    if (priority !== 0) return policy.priority_high_first ? -priority : priority;\n    const created = compare(a.job.created, b.job.created);\n    if (created !== 0) return policy.fifo_ties ? created : -created;\n    return a.index - b.index;\n  });\n  dead.sort((a, b) => {\n    if (policy.dead_order === 'id') {\n      const id = compare(a.job.id, b.job.id);\n      if (id !== 0) return id;\n    }\n    return a.index - b.index;\n  });\n  waiting.sort((a, b) => a.index - b.index);\n  cancelled.sort((a, b) => a.index - b.index);\n\n  return {\n    ready: ready.map(entry => entry.job.id),\n    waiting: waiting.map(entry => ({id: entry.id, at: entry.at})),\n    dead: dead.map(entry => entry.job.id),\n    cancelled: cancelled.map(entry => entry.job.id)\n  };\n}\n",
    "policy.ts": "export const POLICY: any = {\n  base_delay: 200,\n  cancel_wins: false,\n  dead_order: 'input',\n  dedup_key: 'key',\n  delay_cap: 400,\n  exponential: false,\n  fifo_ties: false,\n  max_attempts: 4,\n  priority_high_first: false,\n  retryable_codes: [408, 503],\n  stale_after: 2000,\n  stale_inclusive: false\n};\n",
    "helpers.ts": "export interface IndexedJob {\n  job: any;\n  index: number;\n}\n\nexport function deduplicate(jobs: any[], key: string): IndexedJob[] {\n  const selected = new Map<any, IndexedJob>();\n  jobs.forEach((job, index) => selected.set(job[key], {job, index}));\n  return Array.from(selected.values());\n}\n\nexport function compare(a: number | string, b: number | string): number {\n  return a < b ? -1 : a > b ? 1 : 0;\n}\n\nexport function retryDelay(attempt: number, policy: any): number {\n  if (policy.base_delay === 0) return 0;\n  const factor = policy.exponential ? 2 ** Math.max(0, attempt - 1) : 1;\n  return Math.min(policy.base_delay * factor, policy.delay_cap);\n}\n"
  }
}