Skip to content

Four-pack Explore baseline verification — 2026-08-24 (OGUR-95 / T0.2)

Governing rule: mvp-scope.md — the MVP-2 served-pack contract. PRs #230–#234 shipped four frozen Explore report packs, and four MVP-2 tasks treat "the four-pack baseline" as a fixed reference point they build on: T4.4 (OGUR-124, in-engine pack build + replay + ship verdict), T5.1 (OGUR-126, Gate R scorer — "measure-first: run against all four frozen packs in week 1"), T5.6 (OGUR-131) and T5.7 (OGUR-132, the obesity and cardiometabolic rebuilds). None of them had a record that the reference point holds. This document is that record.

This ticket changed no pack content and no code. Its only product is this file. Where a criterion is met, the row below names the artifact a reader can re-run — a criterion backed by a green test but no transcript is not treated as met.

Revision under test

Branch ouardinik/ogur-95-t02-verify-the-four-pack-baseline-on-main
Base origin/main @ 0f4de975 (chore(agents): add .agents/stack.yml…, #282)
Worktree ogur-wt/ogur-95, created fresh from origin/main; git status clean at verification time
Date 2026-08-24

git rev-parse main in the primary checkout was cde92679stale. The primary checkout also sits on docs/next-parallel-param, not main. Verification therefore ran in a dedicated worktree cut from origin/main, and every command below was run from it.

Configuration was passed explicitly, never inherited. ogur/config.py:230 is SettingsConfigDict(env_file=".env"), resolved against the process CWD. The primary checkout's .env lists only three packs, one of them under a different worktree on an unmerged branch, and leaves SESSION_COOKIE_SECURE at its True default. The ogur-95 worktree has no .env, and all three settings were set on each command line:

DATABASE_URL             = sqlite:///<scratch>/roster.db      (never the live ogur.db)
SESSION_COOKIE_SECURE    = false                              (config.py:173 defaults True; see below)
EXPLORE_REPORT_PACK_PATH = <worktree>/archived_data/gns561_explore/gns561_seed_pack.json
                         : <worktree>/archived_data/polygon_plg101_explore/polygon-cd8-ami-001_seed_pack.json
                         : <worktree>/archived_data/obesity_rnai_explore/obesity-rnai-001_seed_pack.json
                         : <worktree>/archived_data/cardiometabolic_rnai_explore/cardiometabolic-rnai-001_seed_pack.json

The four packs

meta.landscape_id File under archived_data/
gns561-cca-autophagy-001 gns561_explore/gns561_seed_pack.json
polygon-cd8-ami-001 polygon_plg101_explore/polygon-cd8-ami-001_seed_pack.json
obesity-rnai-001 obesity_rnai_explore/obesity-rnai-001_seed_pack.json
cardiometabolic-rnai-001 cardiometabolic_rnai_explore/cardiometabolic-rnai-001_seed_pack.json

GNS561's filename does not follow the <landscape_id>_seed_pack.json convention. Discovery therefore indexes by meta.landscape_id read from the file, never by filename — the same choice tests/unit/api/test_report_pack_integrity.py makes at _pack_paths.

Result

# Criterion Mechanism Evidence Verdict
1 All four packs load through report_pack.py validation _read_packread_textjson.loads_validate_packevidence_depthsources_used (ogur/api/report_pack.py:98-152) Appendix A: 4 discovered, 4 named, 0 problems, both gates. Plus test_report_pack_integrity.py parametrized over all four MET
2 EXPLORE_REPORT_PACK_PATH with four paths serves a four-row grant-filtered roster served_landscape_ids()landscape_ids_for_user() (ogur/api/routes/explore.py:245-251, ogur/store/users.py:130) Appendix B: 4 / 2 / 0 rows and 401 from one server process, plus a live grant change moving 2 → 3 MET
3 pack_replay.py replays one pack into a scratch DB idempotently reconcile_signals; identity (content_hash, landscape_id); ownership marker raw_data.seed_pack (scripts/seed/pack_replay.py:872-934) Appendix C: run 1 inserted=2366, run 2 unchanged=2366 / inserted=0 / deleted=0, and an independent row fingerprint identical across both MET

make lint and make test results are in Appendix D.

Why criterion 2's negative control is the load-bearing part

A four-row roster from a fully-granted identity proves nothing on its own: it is exactly what an unfiltered roster over a four-pack config also returns. The grant filter is established by holding the pack configuration constant and varying only the identity, then by changing a grant while the process runs:

Leg Identity Grants Observed
A ogur95-all 4 200, 4 rows, configured order
B ogur95-two 2 200, exactly the 2 granted; the other 2 absent
C ogur95-none 0 200 {"landscapes":[]} — empty is healthy, not an error (explore.py:236)
D anonymous 401 — distinct from C's empty 200
E ogur95-two 2 → 3 Grant written to the DB with uvicorn not restarted and EXPLORE_REPORT_PACK_PATH unchanged → roster returns 3

Leg E is the decisive one. Config was held still, the database moved, the response moved — so the roster reads grants per request and does not mirror the pack configuration. Legs A–D alone are consistent with a config that merely happens to hold the right number of packs.

Leg F additionally confirms every listed landscape is servable, not just listable: report and figures both 200 for all four. Leg G confirms an ungranted landscape 404s rather than leaking its existence.

Findings — not failures of this ticket

Neither blocks OGUR-95, whose contract requires exactly one pack replayed. Both are recorded because downstream tasks assume otherwise.

F1 — pack_replay.py covers 2 of the 4 packs

REPLAY_SPECS (scripts/seed/pack_replay.py:130) holds entries only for gns561-cca-autophagy-001 and obesity-rnai-001. --landscape-id is choices=sorted(REPLAY_SPECS), so the other two are refused at argparse:

pack_replay.py: error: argument --landscape-id: invalid choice: 'polygon-cd8-ami-001'
  (choose from gns561-cca-autophagy-001, obesity-rnai-001)
pack_replay.py: error: argument --landscape-id: invalid choice: 'cardiometabolic-rnai-001'
  (choose from gns561-cca-autophagy-001, obesity-rnai-001)

The refusal is clean — no database file is created. Adding a landscape is adding a ReplaySpec, not forking the script, which is the documented design. This matters to T4.4 (OGUR-124), whose contract says "Replay via pack_replay.py", and to T5.7 (OGUR-132), the cardiometabolic rebuild.

F2 — the container image carries 2 of the 4 packs

Dockerfile:73 bakes gns561 + polygon only, and both scripts/smoke/smoke_container.sh and scripts/smoke/smoke_production.sh hardcode the same two. Obesity and cardiometabolic validate in tests and serve correctly from a checkout — Appendix B proves all four serve — but they are not in the deployed image. Any task that reads "the four-pack baseline" as "four packs are deployed" is reading it wrong.

The verified claim, stated exactly: all four packs are valid and servable from a checkout, and one of them — obesity-rnai-001 — was replayed into a scratch database idempotently. Replay capability is not a four-pack property: per F1 above, pack_replay.py supports two of the four, which is all T0.2 required. Do not carry "four packs are replay-capable" forward from this document; T4.4 and T5.7 need F1 read first.

Re-running this

# Pin to the SHA this record was made against. `origin/main` MOVES: once it
# advances, the same recipe exercises different code and can no longer reproduce
# the counts below, while still looking like it did.
BASE=0f4de975561068ac34ff89ce27ac31616d3e55fc      # the revision under test, above
git worktree add -b <branch> <path> "$BASE" && cd <path> && uv sync --extra dev
git rev-parse HEAD                                # must echo $BASE
R=$PWD
PACKS="$R/archived_data/gns561_explore/gns561_seed_pack.json:$R/archived_data/polygon_plg101_explore/polygon-cd8-ami-001_seed_pack.json:$R/archived_data/obesity_rnai_explore/obesity-rnai-001_seed_pack.json:$R/archived_data/cardiometabolic_rnai_explore/cardiometabolic-rnai-001_seed_pack.json"
S=$(mktemp -d)

# criterion 1
EXPLORE_REPORT_PACK_PATH="$PACKS" uv run --extra dev python -m pytest \
  tests/unit/api/test_report_pack_integrity.py -q

# criterion 2 — three identities. seed_users.py needs TWO invocations: main()
# processes --grant before --email, so a combined call exits 1 with "no such user".
for E in ogur95-all ogur95-two ogur95-none; do
  PW=$(uv run python -c 'import secrets;print(secrets.token_urlsafe(12))')
  printf '%s' "$PW" > "$S/$E.pw"; chmod 600 "$S/$E.pw"
  printf '%s' "$PW" | DATABASE_URL="sqlite:///$S/roster.db" uv run python scripts/seed/seed_users.py \
    --email "$E@ogur.local" --name "OGUR-95 $E" --org OGUR95 --password-stdin
done
DATABASE_URL="sqlite:///$S/roster.db" uv run python scripts/seed/seed_users.py \
  --grant ogur95-all@ogur.local gns561-cca-autophagy-001 \
  --grant ogur95-all@ogur.local polygon-cd8-ami-001 \
  --grant ogur95-all@ogur.local obesity-rnai-001 \
  --grant ogur95-all@ogur.local cardiometabolic-rnai-001 \
  --grant ogur95-two@ogur.local polygon-cd8-ami-001 \
  --grant ogur95-two@ogur.local obesity-rnai-001
# confirm the grants independently of the API: expect all|4  none|0  two|2
sqlite3 "$S/roster.db" "SELECT u.email, COUNT(a.landscape_id) FROM user u
  LEFT JOIN userlandscapeaccess a ON a.user_id=u.id GROUP BY u.email ORDER BY u.email;"

# boot on a dedicated port so a `make dev` elsewhere cannot be curled by accident.
# REFUSE if 8099 is already held: our process would die on bind while every curl
# below silently succeeded against the OLD server — recording a whole evidence run
# from the wrong database and the wrong pack configuration.
lsof -tiTCP:8099 -sTCP:LISTEN >/dev/null 2>&1 && {
  echo "port 8099 already in use — stop that server first"; exit 1; }

DATABASE_URL="sqlite:///$S/roster.db" SESSION_COOKIE_SECURE=false \
  EXPLORE_REPORT_PACK_PATH="$PACKS" uv run uvicorn ogur.api.app:app \
  --host 127.0.0.1 --port 8099 &          # no --reload: one deterministic process
UVICORN_PID=$!                            # NOT `%1` — see the teardown below
trap 'if [ -n "$UVICORN_PID" ]; then kill "$UVICORN_PID" 2>/dev/null
      wait "$UVICORN_PID" 2>/dev/null; fi' EXIT

# Bounded readiness + liveness. `until curl ...; do :; done` alone spins forever
# when the server never serves, and cannot tell "not up yet" from "died on start".
for _ in $(seq 1 60); do
  kill -0 "$UVICORN_PID" 2>/dev/null || { echo "uvicorn exited before serving"; exit 1; }
  curl -fsS --max-time 2 http://127.0.0.1:8099/health >/dev/null 2>&1 && break
  sleep 1
done
curl -fsS --max-time 2 http://127.0.0.1:8099/health >/dev/null || {
  echo "uvicorn never became ready within 60s"; exit 1; }

# PROVE the responder is ours; do not infer it. The preflight above and uvicorn's
# bind are not atomic, so another process (a second rerun) can take 8099 in the
# gap: our PID is still alive, the health curl succeeds against the COMPETITOR,
# and only later does ours die with EADDRINUSE. Evidence collected in that window
# comes from the wrong database and pack config while looking correct.
# `uv run` means the listener is a DESCENDANT of $UVICORN_PID, not equal to it.
_owned_by() {                        # is $2 an ancestor of $1, or $1 itself?
  _p=$1
  while [ -n "$_p" ] && [ "$_p" -gt 1 ] 2>/dev/null; do
    [ "$_p" = "$2" ] && return 0
    _p=$(ps -o ppid= -p "$_p" 2>/dev/null | tr -d ' ')
  done
  return 1
}
LISTENER=$(lsof -tiTCP:8099 -sTCP:LISTEN | head -1)
_owned_by "$LISTENER" "$UVICORN_PID" || {
  echo "port 8099 is served by pid $LISTENER, which is not our uvicorn ($UVICORN_PID)"
  exit 1; }

# login each identity into its OWN jar; assert set-cookie carries no `Secure`,
# then assert each jar resolves to its own email before trusting any roster
for E in ogur95-all ogur95-two ogur95-none; do
  EMAIL="$E@ogur.local" PASSWORD="$(cat "$S/$E.pw")" python3 -c '
import json,os,sys; json.dump({"email":os.environ["EMAIL"],"password":os.environ["PASSWORD"]},sys.stdout)' \
  | curl -sS -D - -o /dev/null -c "$S/$E.jar" -H 'Content-Type: application/json' -d @- \
      http://127.0.0.1:8099/api/auth/login | grep -Ei '^HTTP|^set-cookie'
  curl -fsS -b "$S/$E.jar" http://127.0.0.1:8099/api/auth/me
done

# legs A/B/C — 4 rows, 2 rows, empty 200; leg D — anonymous 401
for E in ogur95-all ogur95-two ogur95-none; do
  curl -sS -w ' HTTP %{http_code} %{content_type}\n' -b "$S/$E.jar" \
    http://127.0.0.1:8099/api/explore/landscapes
done
curl -sS -o /dev/null -w 'anon HTTP %{http_code}\n' http://127.0.0.1:8099/api/explore/landscapes

# leg E — THE decisive control. Grant a 3rd landscape with uvicorn still running
# and PACKS unchanged; the roster must move 2 -> 3. Without this, a 2-row
# response is indistinguishable from a broken 2-pack config.
DATABASE_URL="sqlite:///$S/roster.db" uv run python scripts/seed/seed_users.py \
  --grant ogur95-two@ogur.local cardiometabolic-rnai-001
curl -fsS -b "$S/ogur95-two.jar" http://127.0.0.1:8099/api/explore/landscapes

# legs F/G — every listed landscape actually serves; an ungranted one 404s
for L in gns561-cca-autophagy-001 polygon-cd8-ami-001 obesity-rnai-001 cardiometabolic-rnai-001; do
  for EP in report figures; do   # BOTH — separate routes, they regress independently
    curl -sS -o /dev/null -w "$L $EP %{http_code}\n" -b "$S/ogur95-all.jar" \
      "http://127.0.0.1:8099/api/explore/landscapes/$L/$EP"
  done
done
curl -sS -o /dev/null -w 'ungranted %{http_code}\n' -b "$S/ogur95-none.jar" \
  http://127.0.0.1:8099/api/explore/landscapes/gns561-cca-autophagy-001/report
kill "$UVICORN_PID"; wait "$UVICORN_PID" 2>/dev/null    # `kill %1` would stop job 1,
                                                       # which is uvicorn only in an
                                                       # otherwise-empty shell
trap - EXIT; UVICORN_PID=            # DISARM. Without this the trap fires again at
                                     # shell exit, killing whatever now holds that
                                     # PID — the exact accident it was added to stop.

# criterion 3 — run twice on an EMPTY scratch DB. Run 1 must show unchanged=0,
# run 2 inserted=0/updated=0/deleted=0 and no foreign-collision WARNING.
# --dry-run proves nothing here: it returns before bind_database().
uv run python scripts/seed/pack_replay.py --landscape-id obesity-rnai-001 --db "$S/replay.db"
sqlite3 "$S/replay.db" "SELECT id||'|'||content_hash||'|'||detected_at FROM signal
  WHERE landscape_id='obesity-rnai-001' ORDER BY id;" | shasum -a 256      # fingerprint BEFORE
uv run python scripts/seed/pack_replay.py --landscape-id obesity-rnai-001 --db "$S/replay.db"
sqlite3 "$S/replay.db" "SELECT id||'|'||content_hash||'|'||detected_at FROM signal
  WHERE landscape_id='obesity-rnai-001' ORDER BY id;" | shasum -a 256      # must be IDENTICAL

Two traps that will otherwise cost an hour:

  1. SESSION_COOKIE_SECURE=false is mandatory over plain http. The default is True (ogur/config.py:173, OGUR-76). Login still returns 200 and still sends set-cookie, but curl discards a Secure cookie on http://, so every later request 401s and reads like an authorization bug. Assert the set-cookie header carries no Secure attribute.
  2. seed_users.py needs two invocations. main() processes --grant before --email, so a combined call exits 1 with no such user. Create the identities, then grant.

Appendix

A. Criterion 1 — per-pack validation transcript

_validate_pack is not the whole gate. _read_pack — what a request actually reaches — additionally derives evidence_depth, whose UndescribedRecordLayer is re-raised as ReportPackUnavailable (report_pack.py:143-148). A pack can pass _validate_pack and still 503. Both gates were run per pack.

Discovery is rooted at archived_data/, not the repository root: rooting at the repo would additionally sweep packs out of .claude/worktrees/, which are on unrelated revisions. The script asserts exactly four files and no duplicate landscape_id.

archive root : /Users/kouardini/Desktop/projects/ogur-wt/ogur-95/archived_data
discovered   : 4 pack file(s)

  cardiometabolic-rnai-001
      path            archived_data/cardiometabolic_rnai_explore/cardiometabolic-rnai-001_seed_pack.json
      _validate_pack  OK
      _read_pack      OK  evidence_depth.classes=4 sources_used=2
  gns561-cca-autophagy-001
      path            archived_data/gns561_explore/gns561_seed_pack.json
      _validate_pack  OK
      _read_pack      OK  evidence_depth.classes=4 sources_used=2
  obesity-rnai-001
      path            archived_data/obesity_rnai_explore/obesity-rnai-001_seed_pack.json
      _validate_pack  OK
      _read_pack      OK  evidence_depth.classes=4 sources_used=2
  polygon-cd8-ami-001
      path            archived_data/polygon_plg101_explore/polygon-cd8-ami-001_seed_pack.json
      _validate_pack  OK
      _read_pack      OK  evidence_depth.classes=4 sources_used=2

landscape_ids : ['cardiometabolic-rnai-001', 'gns561-cca-autophagy-001', 'obesity-rnai-001', 'polygon-cd8-ami-001']
RESULT        : ALL FOUR PACKS PASS BOTH GATES

Exit code 0.

B. Criterion 2 — roster curl transcript

Three identities seeded into a scratch database, passwords generated per identity and passed on stdin (never in argv). Grants confirmed against the table directly, independent of the API:

$ sqlite3 roster.db "SELECT u.email, COUNT(a.landscape_id) FROM user u
                     LEFT JOIN userlandscapeaccess a ON a.user_id=u.id
                     GROUP BY u.email ORDER BY u.email;"
ogur95-all@ogur.local|4
ogur95-none@ogur.local|0
ogur95-two@ogur.local|2

Server: uvicorn ogur.api.app:app --host 127.0.0.1 --port 8099, no --reload, single PID 74885 for the entire transcript. Port 8099 rather than 8000 so a make dev running from another checkout cannot be curled by accident.

Login, all three identities — note the absence of Secure:

HTTP/1.1 200 OK
set-cookie: ogur_session=[redacted]; HttpOnly; Max-Age=1209600; Path=/; SameSite=lax

Each jar resolves to its own identity, which rules out jar cross-contamination:

$ curl -b <jar> http://127.0.0.1:8099/api/auth/me
ogur95-all    ogur95-all@ogur.local  | OGUR95
ogur95-two    ogur95-two@ogur.local  | OGUR95
ogur95-none   ogur95-none@ogur.local | OGUR95

Leg A — ogur95-all, granted 4/4:

$ curl -sS -D - -b ogur95-all.jar http://127.0.0.1:8099/api/explore/landscapes
HTTP/1.1 200 OK
content-type: application/json

{
    "landscapes": [
        {
            "landscape_id": "gns561-cca-autophagy-001",
            "name": "GNS561 — autophagy-directed oncology (cholangiocarcinoma)",
            "lead_asset": "GNS561 (ezurpimtrostat)",
            "sponsor": "GENFIT / GenoScience Pharma",
            "targets": ["PPT1","ULK1","ULK2","ATG7","ATG4B","TFEB","SQSTM1","BECN1","PIK3C3","MAP1LC3B"]
        },
        {
            "landscape_id": "polygon-cd8-ami-001",
            "name": "PLG-101 — CD8 depletion in acute myocardial ischemia-reperfusion",
            "lead_asset": "PLG-101",
            "sponsor": "Polygon Therapeutics",
            "targets": ["CD8A","CD8B","CD3E","PDCD1","CD20","CD14","IL1B","IL6","C5","CCR2","TNF","NLRP3"]
        },
        {
            "landscape_id": "obesity-rnai-001",
            "name": "RNAi therapeutics — obesity",
            "lead_asset": "ARO-INHBE (Arrowhead Pharmaceuticals)",
            "sponsor": "OGUR benchmark — Sleuth deck",
            "targets": ["INHBE","ACVR1C","GRB14","ANGPTL3","ANGPTL4","AGT","ZNF423","CNR1","SPTBN1","FAM13A","CD59","TGFB1","PTGS2","MIR22"]
        },
        {
            "landscape_id": "cardiometabolic-rnai-001",
            "name": "siRNA dual-targeting — cardiometabolic disease",
            "lead_asset": "BEBT-701",
            "sponsor": "OGUR benchmark — Sanofi CI deck",
            "targets": ["PCSK9","ANGPTL3","APOC3","LPA","AGT","CFB"]
        }
    ]
}

Four rows, application/json, in configured order. The content-type assertion matters: frontend/dist/index.html exists, so the SPA fallback is mounted and a path missing its /api prefix returns 200 text/html.

Legs B, C, D — same process, same four-pack config, identity is the only variable:

=== [B] ogur95-two (granted 2/4) ===
HTTP 200 application/json
count = 2
ids   = ['polygon-cd8-ami-001', 'obesity-rnai-001']
ASSERT OK: exactly the 2 granted; the other 2 are absent, not merely reordered

=== [C] ogur95-none (granted 0/4) ===
HTTP 200 application/json
{"landscapes":[]}

=== [D] anonymous (no cookie) ===
HTTP 401
{"detail":"Not authenticated"}

Leg E — live grant change, no restart:

--- before ---
count = 2
--- grant cardiometabolic-rnai-001 to ogur95-two (DB write only) ---
ogur95-two@ogur.local: granted cardiometabolic-rnai-001
--- after (same process, same cookie, same pack config) ---
count = 3
ids   = ['polygon-cd8-ami-001', 'obesity-rnai-001', 'cardiometabolic-rnai-001']
ASSERT OK: 2 -> 3 with config constant. The roster reads grants per request;
           it does not mirror EXPLORE_REPORT_PACK_PATH.

Legs F and G — servability and the ungranted 404:

=== [F] each listed landscape is actually servable, ogur95-all ===
  gns561-cca-autophagy-001     report=200 figures=200
  polygon-cd8-ami-001          report=200 figures=200
  obesity-rnai-001             report=200 figures=200
  cardiometabolic-rnai-001     report=200 figures=200

=== [G] ungranted landscape, ogur95-none ===
  gns561 as ogur95-none: HTTP 404

The uvicorn log recorded no errors across the whole transcript.

C. Criterion 3 — replay counts on the scratch database

Pack: obesity-rnai-001 — the generic replay path, and the one T4.4 depends on. gns561 is the landscape the script was generalized from, so it is the weaker test of the generic path. Scratch DB deleted first, so run 1 starts empty; run() calls bind_database() then create_tables(), so no pre-existing schema is needed. --dry-run was not used as evidence — it returns before bind_database and never opens a database.

resolve_db_path refuses any target whose basename is ogur.db without --allow-live; --allow-live was never passed, and the TARGET DATABASE line printed on both runs names the scratch path.

Run 1 (empty DB):

TARGET DATABASE : <scratch>/replay.db
SEED PACK       : <worktree>/archived_data/obesity_rnai_explore/obesity-rnai-001_seed_pack.json
LANDSCAPE       : obesity-rnai-001

Signals built from the pack:
  trials        21
  patents      278
  papers       126
  companies   1941
  TOTAL       2366

Landscape row: obesity-rnai-001
  scope_type       = modality_target
  modalities       = ['siRNA', 'RNAi', 'antimiR', 'oligonucleotide']
  targets          = ['INHBE', 'ACVR1C', 'GRB14', 'ANGPTL3', 'ANGPTL4', 'AGT', 'ZNF423',
                      'CNR1', 'SPTBN1', 'FAM13A', 'CD59', 'TGFB1', 'PTGS2', 'MIR22']
  indications      = ['obesity', 'overweight', 'weight management', 'metabolic syndrome',
                      'type 2 diabetes', 'MASH', 'NASH']
  min_target_count = 1

Reconciled the rows THIS pack owns (marker: raw_data.seed_pack):
  trials     inserted=   21  updated=    0  unchanged=    0
  patents    inserted=  278  updated=    0  unchanged=    0
  papers     inserted=  126  updated=    0  unchanged=    0
  companies  inserted= 1941  updated=    0  unchanged=    0
  TOTAL      inserted= 2366  updated=    0  unchanged=    0
             deleted =    0  (pack-owned rows the pack no longer contains; 0 linkage edge(s) removed with them)
             live rows on this landscape are never touched

Run 2 (identical command, same DB):

Reconciled the rows THIS pack owns (marker: raw_data.seed_pack):
  trials     inserted=    0  updated=    0  unchanged=   21
  patents    inserted=    0  updated=    0  unchanged=  278
  papers     inserted=    0  updated=    0  unchanged=  126
  companies  inserted=    0  updated=    0  unchanged= 1941
  TOTAL      inserted=    0  updated=    0  unchanged= 2366
             deleted =    0  (pack-owned rows the pack no longer contains; 0 linkage edge(s) removed with them)
             live rows on this landscape are never touched

Neither run emitted the WARNING: N pack record(s) collide with a row this replay does not own block (grep -c WARNING = 0 on both). That warning is driven by GroupStats.foreign, which is never printed per group — only as the aggregate — so its absence is part of the evidence, not an inference.

Independent check. The script reports its own statistics, so unchanged=2366 and "the rows did not change" are different claims. Signal.id is a fresh uuid4 per insert and detected_at is deliberately excluded from _RECONCILED_FIELDS, which makes them the sharp invariants: a delete-then- reinsert cycle preserves the counts but changes both.

                                   after run 1              after run 2
counts by landscape        obesity-rnai-001|2366    obesity-rnai-001|2366
pack-owned rows                            2366                     2366
signaldrug edges                              0                        0
sha256(id|content_hash|detected_at)  1df294082dadaf8c9fc06427eb371467de6570c8de560e3aa1fef52943818bae
                                     1df294082dadaf8c9fc06427eb371467de6570c8de560e3aa1fef52943818bae

diff of the two fingerprints is empty. The row-id set, the content-hash set and the detected_at set all survived run 2 unchanged — the replay reconciled, it did not rebuild.

The whole database file is deliberately not hashed: get_or_create_landscape sets landscape.last_updated = utcnow() unconditionally on every run, and SQLite page layout churns, so a file hash produces a false negative.

D. Gates

make lint and make test were run in the ogur-95 worktree with the four-path EXPLORE_REPORT_PACK_PATH above and DATABASE_URL pointed at a scratch file, so the suite could not read or write the live ogur.db. make fmt was not run — the repository-wide format check fails at baseline.

$ make lint
uv run ruff check ogur/ tests/ scripts/
All checks passed!

$ make test
3342 passed, 3 skipped, 5 deselected, 21140 warnings in 187.39s (0:03:07)
exit 0

The parametrized pack gate, run separately with -v so each pack is named rather than counted — note test_the_committed_pack_matches_a_fresh_build, which asserts a byte-identical offline rebuild and now covers all four (UNREPRODUCIBLE is an empty set at test_report_pack_integrity.py:62):

test_every_committed_pack_passes_the_loaders_own_validator[cardiometabolic-rnai-001] PASSED
test_every_committed_pack_passes_the_loaders_own_validator[gns561-cca-autophagy-001] PASSED
test_every_committed_pack_passes_the_loaders_own_validator[obesity-rnai-001]         PASSED
test_every_committed_pack_passes_the_loaders_own_validator[polygon-cd8-ami-001]      PASSED
test_every_committed_pack_loads_through_the_cached_reader[cardiometabolic-rnai-001]  PASSED
test_every_committed_pack_loads_through_the_cached_reader[gns561-cca-autophagy-001]  PASSED
test_every_committed_pack_loads_through_the_cached_reader[obesity-rnai-001]          PASSED
test_every_committed_pack_loads_through_the_cached_reader[polygon-cd8-ami-001]       PASSED
test_the_committed_pack_matches_a_fresh_build[cardiometabolic-rnai-001]              PASSED
test_the_committed_pack_matches_a_fresh_build[gns561-cca-autophagy-001]              PASSED
test_the_committed_pack_matches_a_fresh_build[obesity-rnai-001]                      PASSED
test_the_committed_pack_matches_a_fresh_build[polygon-cd8-ami-001]                   PASSED

119 passed, 1 warning in 13.08s

make docs-build (mkdocs build --strict) was run after adding this file to the mkdocs.yml nav — validation.omitted_files is warn and --strict promotes it, so a product doc missing from the nav fails the build.