Resolved policy after all six updates:
- base_delay 200, exponential false, max_attempts 4, retryable_codes [408, 503]
- cancel_wins false, dedup_key "key", fifo_ties false, priority_high_first false
- dead_order "input", delay_cap 400
- stale_after 2000, stale_inclusive false

Design assumptions:
- Payload carries `now` and `jobs`. The spec says "Input now integer", so I read `now` from the payload and take the jobs from `payload.jobs`.
- Dedup keeps the last job for each dedup value, at that job's original index. Output order follows the kept jobs' original indices.
- A job missing the dedup field is deduplicated by `undefined`. I treat missing fields as unique and never merge them.
- Failure exists when `last_code` is nonzero. For a retryable job with failure, due = max(due, failed_at + min(base_delay * (exponential ? 2**max(0, attempt-1) : 1), delay_cap)).
- Cancelled jobs go to cancelled if cancel_wins or the job is not retryable. With cancel_wins false, a cancelled retryable job continues through the normal flow.
- The dead check is stale, or attempt >= max_attempts, or (last_code nonzero and not retryable).
- Ready sort is priority ascending (priority_high_first false), then created descending (fifo_ties false), then index.
- Dead sort is by index, since dead_order is "input".

```json
{"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  base_delay: 200,\n  exponential: false,\n  max_attempts: 4,\n  retryable_codes: [408, 503],\n  cancel_wins: false,\n  dedup_key: 'key',\n  fifo_ties: false,\n  priority_high_first: false,\n  dead_order: 'input',\n  delay_cap: 400,\n  stale_after: 2000,\n  stale_inclusive: false\n};\n","helpers.ts":"export function dedup(jobs: any[], key: string): {job: any, idx: number}[] {\n  const last = new Map<any, number>();\n  jobs.forEach((j, i) => { last.set(j[key], i); });\n  const out: {job: any, idx: number}[] = [];\n  jobs.forEach((j, i) => { if (last.get(j[key]) === i) out.push({job: j, idx: i}); });\n  return out;\n}\n","core.ts":"import {dedup} from './helpers.ts';\n\nexport function run(payload: any, policy: any): any {\n  const now = payload.now;\n  const jobs: any[] = payload.jobs || [];\n  const items = dedup(jobs, policy.dedup_key);\n  const ready: any[] = [], waiting: any[] = [], dead: any[] = [], cancelled: any[] = [];\n  for (const it of items) {\n    const j = it.job;\n    const code = j.last_code || 0;\n    const retryable = policy.retryable_codes.includes(j.last_code);\n    if (j.cancelled && (policy.cancel_wins || !retryable)) { cancelled.push(it); continue; }\n    const age = now - j.created;\n    const stale = policy.stale_inclusive ? age >= policy.stale_after : age > policy.stale_after;\n    if (stale || j.attempt >= policy.max_attempts || (code !== 0 && !retryable)) { dead.push(it); continue; }\n    let due = j.due;\n    if (retryable && code !== 0) {\n      const mult = policy.exponential ? Math.pow(2, Math.max(0, j.attempt - 1)) : 1;\n      const d = j.failed_at + Math.min(policy.base_delay * mult, policy.delay_cap);\n      due = Math.max(due, d);\n    }\n    if (due > now) waiting.push({it, at: due}); else ready.push(it);\n  }\n  ready.sort((a, b) => {\n    const pa = a.job.priority, pb = b.job.priority;\n    if (pa !== pb) return policy.priority_high_first ? pb - pa : pa - pb;\n    const ca = a.job.created, cb = b.job.created;\n    if (ca !== cb) return policy.fifo_ties ? ca - cb : cb - ca;\n    return a.idx - b.idx;\n  });\n  if (policy.dead_order === 'id') {\n    dead.sort((a, b) => (a.job.id < b.job.id ? -1 : a.job.id > b.job.id ? 1 : a.idx - b.idx));\n  } else dead.sort((a, b) => a.idx - b.idx);\n  waiting.sort((a, b) => a.it.idx - b.it.idx);\n  cancelled.sort((a, b) => a.idx - b.idx);\n  return {\n    ready: ready.map(x => x.job.id),\n    waiting: waiting.map(w => ({id: w.it.job.id, at: w.at})),\n    dead: dead.map(x => x.job.id),\n    cancelled: cancelled.map(x => x.job.id)\n  };\n}\n"}}
```