add the rewrite charter and its decision records

This commit is contained in:
justinzeus 2026-08-20 11:34:31 +02:00
parent a8c5939804
commit 41e8714ca3
4 changed files with 519 additions and 0 deletions

View file

@ -0,0 +1,87 @@
# Scholarr rewrite - testing strategy **[live 2026-07-21]**
This is an agreed direction from the 2026-07-21 discussion with Justin, to be formalized during
spec freeze. Part of the [scholarr-rewrite](README.md) runbook; read the doctrine there first.
This document records how the rewrite proves itself correct. It is a decision record, not the final
spec: it feeds the spec set and defines the release gates below.
## Core principle
**Deterministic tests against recorded reality.** The service's hard logic (matching, dedup,
scheduling, backoff) must be testable with **zero network**. Nothing that matters to correctness
depends on a live provider being reachable at test time.
## Golden corpus
Two recorded artifacts become **permanent fixtures in the repo** (anonymized where needed):
- The **recovered v1 database**: 25,698 real publications, 492 profiles with real edge cases.
- The **calibration run's cached OpenAlex responses**.
These are the ground for deterministic replay: the matcher and dedup logic are exercised against
real data and real provider payloads without touching the network.
## The five pillars
1. **Pure logic** (normalization, fingerprinting, identifier parsing, confidence scoring):
- table tests;
- **property-based tests** for the invariants that must always hold: normalization is
idempotent, dedup is order-independent, merge is commutative;
- **Go native fuzzing** on every parser that touches external text or paste input.
2. **Provider clients:**
- **contract tests** replaying recorded HTTP fixtures via `httptest`, including the ugly cases:
`429` with and without `Retry-After`, truncated JSON, empty pages;
- the **rate limiter and cooldown state machine** tested with a **fake clock**;
- the **2026-07-21 OpenAlex IP block becomes a regression case** so the system's handling of an
IP-level block is proven, not hoped.
3. **Sync engine** - executable invariants:
- one active run per user;
- idempotent re-runs;
- additive-only baseline import;
- crash-mid-run leaves resumable state;
- **race detector in CI**, plus a **concurrent-write hammer test**, because single-writer
discipline is the main risk of the SQLite-only design.
4. **Migrations:**
- every migration tested **up and down** against a **real-database copy**;
- plus a **seeded prior-version DB in CI**, so upgrades are proven **pre-release**.
5. **End-to-end smoke:**
- the binary boots in CI with a **seeded SQLite** and a **stub provider**;
- a **scripted curl** run walks the full API flow: onboard, import, sync, review-resolve, read,
export.
- **No browser automation.** UI QA is manual by Justin against the frozen design contract
(`/opt/stacks/scholarr-rewrite/design/DESIGN.md`). See the working-conventions block
in [README.md](README.md#conventions-for-any-agent-working-this-project).
## Dry runs are a product feature
Not test-only scaffolding, actual product behavior that also serves as the QA instrument:
- **bulk import previews** before creating anything;
- **`--dry-run`** on sync and on destructive admin actions.
## Acceptance
**Shadow-run** with the real ~253-author list for **2 to 3 weeks**, alongside the dad's existing
JS-script habit, and **diff what each caught**. This is the **release flip criterion** and follows
the conductarr-soak pattern.
## Release gates, in order
1. unit + property + fuzz green;
2. race detector green;
3. migration up/down green;
4. e2e smoke green;
5. **golden-corpus ratchet** - matcher changes may not regress the recorded auto-match baseline;
6. tagged release with a **tested backup/restore path documented**.
## Related
- The recovered v1 DB and calibration cache that become fixtures: [README.md](README.md) (Assets),
[identity-calibration.md](identity-calibration.md).
- Manual-QA rule (no browser automation): a working convention of this project, stated in
[README.md](README.md#conventions-for-any-agent-working-this-project).