> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prodbreak.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Make CI deterministic

> Collapse durations so cascades fire inline, in order, with no flake.

Time is the usual source of flake in integration tests. ProdBreak gives you deterministic control of
it. Today's MVP lever is **collapsing named durations to `0`**; freeze-in-place mode (the eventual CI
default) is on the roadmap.

## The pattern

Set the pack's named durations to `0` in your test setup. The timer queue then drains **in order on
the triggering call** — no waiting on wall-clock:

```ts theme={null}
beforeEach(async () => {
  await sandbox.clock.setDurations({ run_settle: "0s", transcription: "0s" });
});
```

Now a cascade runs to completion synchronously:

```ts theme={null}
const run = await deck.taskRuns.create({ taskId: "task_rent" });
await sandbox.clock.advance("0s");      // every due event fires, in order, before this returns
const done = await deck.taskRuns.retrieve(run.id);
expect(done.status).toBe("completed");  // no polling, no sleep, no flake
```

## What you get today vs. with freeze mode

<CardGroup cols={2}>
  <Card title="Deterministic now (durations→0)" icon="circle-check">
    Event **ordering**, "did the cascade fire?", and **relative** timing assertions are fully
    deterministic. This covers the large majority of integration tests.
  </Card>

  <Card title="Needs freeze mode (roadmap)" icon="snowflake">
    Assertions on **exact absolute timestamps** (`created_at == "2025-01-01T00:00:05Z"`) want
    freeze-in-place plus a pinned `t0`, since absolute stamps still track wall-clock until then.
  </Card>
</CardGroup>

<Tip>
  Pin `t0` per world when a test is date-sensitive — month-end billing, DST, year rollover — so the
  canonical start is reproducible regardless of when CI runs:

  ```ts theme={null}
  await sandbox.reset({ t0: "2025-01-31T23:59:00Z" });
  ```
</Tip>

## Why not just sleep?

A `sleep(5000)` is slow *and* flaky — it assumes delivery happens within a window. Collapsing
durations removes the window entirely: the work is done by the time `advance()` returns. Faster suites,
zero timing assumptions.
