# VERIFY.md — how to independently verify the preregistration

## What you're checking

A preregistration is only worth anything if a third party can verify:
1. The hypothesis text hasn't changed since sealing
2. The feature definitions were pinned before results were visible
3. Every definitional change since sealing is logged and traceable
4. No artifact was quietly omitted from the set

This file gives the literal commands to check all four. No email to us required.

## Prerequisites

You need: `sha256sum`, `python3`, `jq`, and `git` — all standard on Linux/macOS.

## 1. Verify the seal (hypothesis text unchanged)

```bash
cd v115_physical_twin

# Check the hypothesis file against the seal in STAMP.txt
sha256sum PREREGISTRATION_PHYSICAL_TWIN.md
# Expected: 95c34280a6d209b16f69b40efdf7d4f69e390bc9f568f256b10bb8d338cd5090

# Cross-check against STAMP.txt
grep 95c34280 STAMP.txt
# Should print the same hash
```

If the hash differs, the hypothesis was edited after sealing. Every result
derived from it must be discarded.

## 2. Verify the manifest (no artifact omitted)

```bash
# Recompute the root hash over all listed artifacts
grep -E '^[a-f0-9]{64}  ' MANIFEST.txt | sort -k2 | sha256sum
# Expected: da83aaa52471823d857d0e094361e05f05158ff778ae54cb97a4bd66d5fa03ef

# Compare to the root hash claimed in MANIFEST.txt
grep 'Root hash:' MANIFEST.txt
# Should print the same hash
```

If the hashes differ, either a file was tampered with or the manifest was
edited without updating the root hash.

To verify each individual file:

```bash
while read hash file; do
  computed=$(sha256sum "$file" | cut -d' ' -f1)
  if [ "$hash" = "$computed" ]; then
    echo "  OK  $file"
  else
    echo "  FAIL $file (expected $hash, got $computed)"
  fi
done < <(grep -E '^[a-f0-9]{64}  ' MANIFEST.txt)
```

## 3. Walk the chain (every definitional change logged)

```bash
# The current pin
cat PIN_CHAIN.json | jq '.chain_version, .pinned_at, .seal_hash, .manifest_root_hash'

# The chain: each pin carries the hash of the pin it supersedes.
# Version 1 (this one) has supersedes=null — it's the first link.
# Future versions will have supersedes_hash = the sha256 of the prior PIN_CHAIN.json.
#
# To walk the chain:
# 1. Start with the current PIN_CHAIN.json
# 2. Read its supersedes_hash field
# 3. If non-null, find the prior PIN_CHAIN.json with that hash
# 4. Repeat until supersedes_hash is null (the first link)
#
# Each link in the chain contains a definition_changes_since_seal array.
# Walking from current back to version 1 shows every re-cut in order.

# Verify the current pin's self-hash
sha256sum PIN_CHAIN.json
# This is the hash the NEXT pin will carry in its supersedes_hash field.
```

## 4. Verify the seal predates the data (timing)

Git commit dates are client-supplied and settable to anything — a commit
hash alone does not prove when. Independent time evidence:

**a. Wayback Machine save (triggered 2026-08-13T16:14:32Z).** The
utilisation page footer contains the manifest root hash. A Wayback Machine
snapshot captures both the page content and the timestamp. A hash visible
in an August snapshot cannot have been computed from data that didn't exist
until November.

```bash
# Check the Wayback snapshot:
curl -s "https://web.archive.org/web/20260813161432/https://kairossignal.com/utilisation" | grep da83aaa5
```

**b. OpenTimestamps receipt (MANIFEST.txt.ots).** The manifest file has
been anchored to the Bitcoin blockchain via OpenTimestamps. Once the
Bitcoin confirmation lands (typically within 1-3 hours), the timestamp is
verifiable independently of any single company's records:

```bash
ots verify MANIFEST.txt.ots
# Shows: "Pending confirmation" until the next Bitcoin block, then "Verified"
```

**c. IndexNow submission.** The utilisation page was submitted to IndexNow
on 2026-08-13, creating a crawl request timestamp from a third-party
search infrastructure.

**d. Root history (ROOT_HISTORY.txt).** Every manifest root that has ever
been live is listed here with the dates it was active. A reader can check
that a root visible in an old crawl matches a root we acknowledge. A root
in a crawl but not in this list is either a forgery or a root we've
disowned.

```bash
cat ROOT_HISTORY.txt
# Append-only: past roots stay resolvable after they're replaced
```

**e. GitHub push record.** If pushed to GitHub, the push event has a
server-side timestamp visible in the repo's activity log. This is weaker
than (a)-(d) but provides another independent source.

## 5. Walk the chain (every definitional change logged with direction)

```bash
# The current pin
cat PIN_CHAIN.json | jq '.chain_version, .pinned_at, .seal_hash, .manifest_root_hash'

# Each change entry now carries an effect field:
#   series_added      — new networks/concepts became visible
#   series_removed    — a network dropped from the test set
#   denominator_changed — a utilisation pair's denominator was corrected
#   pair_refused      — a pair was refused from a ratio table
#
# Plus pre_value, post_value, direction, and test_set_impact.
# A reader can see not just WHAT changed but WHICH WAY the affected
# utilisation figure went and whether it moved a network into or out
# of the test set.

cat PIN_CHAIN.json | jq '.definition_changes_since_seal[] | {date, effect, direction, test_set_impact}'

# The chain: each pin carries the hash of the pin it supersedes.
# Version 1 (this one) has supersedes=null — it's the first link.
# Future versions will have supersedes_hash = the sha256 of the prior PIN_CHAIN.json.
#
# To walk the chain:
# 1. Start with the current PIN_CHAIN.json
# 2. Read its supersedes_hash field
# 3. If non-null, find the prior PIN_CHAIN.json with that hash
# 4. Repeat until supersedes_hash is null (the first link)
#
# V1 is over-anchored: Wayback save + OpenTimestamps + IndexNow.
# Subsequent links inherit strength from the link before them,
# but v1's strength equals its external timestamps alone.

# Verify the current pin's self-hash
sha256sum PIN_CHAIN.json
# This is the hash the NEXT pin will carry in its supersedes_hash field.
```

```bash
cd /home/kairosliquid/propintel
python3 depin_canonical_metrics.py
# Expected: PASS with 40 concepts, 97 natives, 7 self-test properties
```

The self-test enforces:
1. Well-defined (no native maps to two concepts)
2. Total (every concept has a unit)
3. Unit-coherent (pair halves share a unit)
4. Disjoint from refusals
5. Graded (every concept has a comparability grade)
6. Population-coherent (each ratio type has the correct population combination)
7. Fill-rate pairs reference valid concepts

## 6. Verify the tradability archive

```bash
# Point-in-time tradability (should have one row per measurable network per day)
curl -s "http://localhost:8123/?user=default&password=kairos" \
  --data "SELECT snapshot_date, count() as networks, countIf(token_alive=1) as alive FROM depin_tradability GROUP BY snapshot_date ORDER BY snapshot_date FORMAT TabSeparated"
```

## What this doesn't prove

- It doesn't prove we haven't run the test already and are selectively
  reporting. The seal + chain + timeline make this harder, but the only
  real defense is the archive: if we'd tested, we'd have the code, and
  the code would show when it was run.
- It doesn't prove the mappings are correct — only that they're traceable.
  A wrong mapping that's been logged and corrected is honest; a wrong
  mapping that's been silently changed is not. The chain distinguishes them.
- It doesn't prove the collector data is accurate — only that it's
  archived with timestamps and verify URLs. Accuracy is verified by
  following the verify_url on each row to the upstream endpoint.