# DebugHandle

> Talos next · Since 0.7

`ctx.debug`: diagnostics a behavior reads for itself, never for gameplay.

Not simulation time.

## Signature

```ts
export interface DebugHandle {
  /**
   * Real milliseconds since the host started, monotonic, from the platform's clock: for a script
   * timing its own work (`const t = ctx.debug.wallMs(); ...; ctx.log("cost", ctx.debug.wallMs() - t)`).
   * `performance.now()` cannot do that: it is the tick's simulation time, the same for every read
   * in a tick.
   *
   * **Not for gameplay state.** It differs on every run and on replay: a value from it kept in
   * `ctx.state`, or a branch taken on it, makes the run diverge. Behavior sources may not call it
   * (the engine's sim-scope scan fails on one); tools and tests may.
   */
  wallMs(): number
}
```

Import: `import type { DebugHandle } from "@argus/api"`

## Members

| Member | Signature | Description |
|---|---|---|
| `wallMs` | `wallMs(): number` | Real milliseconds since the host started, monotonic, from the platform's clock: for a script timing its own work (`const t = ctx.debug.wallMs(); ...; ctx.log("cost", ctx.debug.wallMs() - t)`). `performance.now()` cannot do that: it is the tick's simulation time, the same for every read in a tick. **Not for gameplay state.** It differs on every run and on replay: a value from it kept in `ctx.state`, or a branch taken on it, makes the run diverge. Behavior sources may not call it (the engine's sim-scope scan fails on one); tools and tests may. |

## Example

The tested fixture `fixtures/host/spinner.ts`.

```ts
import type { Behavior } from "@argus/api"
// Busy-loops ~5 ms per tick. Gate: reported after 10 consecutive overruns of the 2 ms budget, event carries ms, keeps running.
export default {
  update(ctx) {
    const until = ctx.debug.wallMs() + 5
    let x = 0
    while (ctx.debug.wallMs() < until) x += 1
    ctx.state.spins = x
  },
} satisfies Behavior
```
