---
title: Sightings
description: A sighting is one run's view of one record. What it holds, how outcomes are decided, and why the last 30 are kept.
sidebar:
  order: 12
---

## What it is

Every time a run sees a record, the write contract appends a sighting to that record's `sightings` list: which run, when, which producer, the values it saw, and what happened (new, updated, unchanged), plus any drop reason. A record keeps its last 30 sightings.

## Why it exists

Sightings answer "when did this first appear, how often does it come back, and what changed?" without a separate history store. They also make writes idempotent: a run that already left a sighting on a record does not leave another.

## How it works

For each record in a run input:

1. If the record already has a sighting with this run id, the earlier outcome is reused and nothing is rewritten.
2. Otherwise the outcome is decided:
   - `new` when no document exists;
   - `updated` when this producer's values or the record's status changed;
   - `unchanged` otherwise.
3. The sighting `{run, at, producer, values, outcome, dropReason}` is appended. When a person's keep overrode a filter, it also carries `note: "kept by person"`.
4. The list is trimmed to the last 30.
5. `display` is recomputed from `bySource` and sightings.

The run's `counts` add up the outcomes, and `dropped` counts records dropped by filters in that run.

## Worked example

The Senior Shopify Engineer role appears in runs on 2 and 5 November. On 5 November the posting adds a salary. The record's sightings:

```json
[
  {"run": "2026-11-02-2200", "at": "2026-11-02T22:00:04Z", "producer": "hiring-signals", "outcome": "new", "dropReason": null, "values": {"title": "Senior Shopify Engineer", "...": "..."}},
  {"run": "2026-11-05-2200", "at": "2026-11-05T22:00:03Z", "producer": "hiring-signals", "outcome": "updated", "dropReason": null, "values": {"title": "Senior Shopify Engineer", "salary_max": 180000, "...": "..."}}
]
```

On the Desk the record page shows both, and the sparkline shows how often it was seen.

A role a person kept after `title_keywords` dropped it gets sightings like:

```json
{"run": "2026-11-05-2200", "outcome": "updated", "dropReason": null, "note": "kept by person", "...": "..."}
```

## Reference

| Field | Notes |
|---|---|
| `run` | Run id |
| `at` | The run's time |
| `producer` | Producer id |
| `values` | The values this producer reported in this run |
| `outcome` | `new`, `updated` or `unchanged` |
| `dropReason` | The filter's reason, or null |
| `note` | `kept by person` when a keep overrode a filter |

Limit: `MAX_SIGHTINGS` is 30.

## Common pitfalls

- **Using sightings as a full audit log.** Only the last 30 are kept. Long-lived records lose their oldest sightings.
- **Rerunning with a new run id to "refresh".** That is a new run and adds a sighting. Rerun with the same run id to finish a half-applied run.

## Related

- [Records](/concepts/records)
- [The store and the write contract](/concepts/store-and-write-contract)
