# Session Timeline

The session timeline is the [Sensor](/harness/overview) side of the harness made durable: a single, append-only, attributed record of everything that happened to a change. The enforced gates emit into it automatically, so verify verdicts, breaker state, and spend all land on one auditable timeline.

## Commands

```sh
forge trace record --change <c> --kind <kind> --summary "<text>"
forge trace show   --change <c>
```

Events are stored as append-only JSONL:

```text
.forge/changes/<c>/session-log.jsonl
```

Each event carries:

| Field | Meaning |
| --- | --- |
| `seq` | Monotonic sequence number |
| `at` | Timestamp (RFC3339) |
| `kind` | Event category (e.g. `verify`, `budget`, `tool`, `note`) |
| `summary` | Human-readable one-liner |
| `actor` | Contributor attribution (see [Team collaboration](/features/team)) |
| `fields` | Optional structured extras |

## The gates emit automatically

The [verify circuit-breaker](/harness/circuit-breaker) and the [spend budget](/harness/budget) gate both write into this timeline on their own. So verify verdicts, breaker open/closed transitions, and every spend record become timeline events without any extra wiring.

::: info Best-effort emission never changes a verdict
Timeline writes are best-effort. If a log write fails, the gate's outcome is unchanged — a broken log will never turn a FAIL into a PASS or a block into a pass. The gate decides on the counter; the timeline just records what it decided.
:::

## Auto-resolving the active change

When `--change` is omitted, `trace record` and `budget record` **auto-resolve** the single active change under `.forge/changes/`:

- exactly one active change → that change is used;
- zero or more than one active change → the command **fails loudly**.

This is what lets a [live-agent hook](/harness/live-agent-hooks) call these commands *blind* — without knowing the change name in advance.

## `trace show`

`trace show` renders a compact timeline, one event per line:

```text
[seq] <at> <kind> — <summary>  · <actor>
```

Example with two contributors:

```text
[1] 2026-07-15T09:02:11Z note   — change opened: checkout redesign  · María <maria@acme.dev> (backend)
[2] 2026-07-15T09:14:52Z tool   — agent tool use                    · Claude (agent)
[3] 2026-07-15T09:15:03Z budget — 600/1000 tokens — within limits    · Claude (agent)
[4] 2026-07-15T09:31:40Z verify — Verdict: FAIL (1/3)                · Claude (agent)
[5] 2026-07-15T09:48:19Z verify — Verdict: PASS (streak reset)       · María <maria@acme.dev> (backend)
```

The [dashboard](/features/dashboard) renders the same timeline per change, so the record you see on the CLI is the record teammates see in the browser.

::: tip One timeline, many sources
Because the gates and your hooks all write to the same append-only log, you get a single ordered, attributed history of a change — who ran what, what the gates decided, and how spend accumulated.
:::

## Next steps

- [The enforcement doctrine](/harness/overview) — the Guides-and-Sensors model the timeline completes.
- [Verify circuit-breaker](/harness/circuit-breaker) — a gate that emits verdicts into the timeline.
- [Spend budget](/harness/budget) — the other gate that emits automatically.
- [Connect a live agent](/harness/live-agent-hooks) — feeding the timeline blind from a host hook.
- [Team collaboration](/features/team) — how each event gets attributed to a contributor.
