# NODAL track record — original rows and their SHA-256 fingerprint

On 31 October 2026 NODAL changed how its public track record leads: the headline now measures each
call from the engine's market price after estimated costs (see the changelog). The original record
is published here **unaltered**, so anyone can check that no stored call was rewritten.

## The files

| File | What it is |
|---|---|
| `track-original-2026-10-31.jsonl` | Every closed call in the track record's store at 2026-10-31 11:41 UTC — 377 rows |
| `track-original-2026-10-31.jsonl.sha256` | The SHA-256 of that file |
| `track-unreached-entry-2026-10-31.json` | The 39 calls whose recorded entry the market never traded at, and how that was checked |

SHA-256: `9e4660660fdfb2a53380cf0e4094444510cdc4d2e89ef7f4301ccd6163699a91`

## What was hashed

Every key with the prefix `closed:` in the track worker's KV namespace, read at export time. A
closed row is written once, when the call resolves, and never again. Calls still open at export
are not in the file; they are scored both ways when they resolve.

Stored rows expire 400 days after they resolve. This file does not, so it is the permanent copy.

## Canonical form

1. One line per row, sorted by KV key ascending. Keys are `closed:<13-digit epoch ms>:<SYMBOL>`,
   so this order is also chronological.
2. Each line is the JSON object `{"key": <kv key>, "value": <the stored row>}`, serialised with
   [RFC 8785 JSON Canonicalization](https://www.rfc-editor.org/rfc/rfc8785): object keys sorted by
   UTF-16 code units, no whitespace, numbers in ECMAScript shortest round-trip form.
3. Every line ends with a single LF (`\n`). UTF-8, no byte-order mark.
4. The fingerprint is the lowercase hex SHA-256 of the whole file's bytes.

The stored rows were written by `JSON.stringify`, so step 2 changes only the order of their keys,
never a value.

## How to verify

Download both files, then run either:

```
sha256sum -c track-original-2026-10-31.jsonl.sha256
```

or, from a checkout of the repository:

```
node scripts/track-fingerprint.mjs
```

which recomputes the hash, re-serialises every row to confirm the file is already in canonical
form, and (with `--live`, read-only, needs Cloudflare access) compares each row with the live store.

## What the rows contain

Each row is a call exactly as the track worker stored it: symbol, direction, `logged_at`,
`price_at` (the middle of the suggested entry zone — the original method's entry), `entryLow`,
`entryHigh`, `tp1`, `sl`, stated confidence, `status` (which of target or stop was hit first, or
expired), `resolved_at` and `outcome_pct` (the original method's % result), plus the context and
excursion fields added over time.
