# Adopting an existing suite

Surfex's process (spec §18) assumes new work: a test is written, fails, and passes once
the code exists, and that red→green is the evidence a relation rests on. An established
project's tests already pass. They can't honestly go red, so without help every relation
would need a review before Surfex reports anything useful, and again after each refactor.

`adoption:` in `.surfex.exs` decides how much of the existing suite is taken on trust
(spec §18.1).

## Trust or re-evaluate

| Setting | Use it when |
|---|---|
| `:reevaluate` (the default) | the suite is new, small, or nobody can vouch for it; or the project wants every relation earned |
| `:trust` | the suite has been kept honest for a long time: written test-first, reviewed, run in CI on every change |
| `[trust: globs, reevaluate: globs]` | a well-kept core beside tests nobody has read in a while |

Per area, the globs lie within `tests:` and don't overlap. A test matched by neither is
re-evaluated:

```elixir
adoption: [trust: ["test/core/**/*_test.exs"], reevaluate: ["test/legacy/**/*_test.exs"]]
```

Trust is a statement about the tests, so make it where you'd defend it. Re-evaluating a
test later is always possible. Trusting more later is not.

## The baseline

Under trust, adoption is: tag, run green, take the baseline.

```
# 1. Write @tag verifies: on the tests that verify each spec unit: the review work.
mix test
mix surfex.baseline --note "test-first since 2023, reviewed in every MR"
mix surfex.confirm --evidence
```

**Tag first.** The baseline adopts the `verifies:` tags already written; it doesn't create
them, and it is one-shot. A tag added afterwards is an ordinary claim, proposed until its
test fails and passes or someone reviews it, one at a time. So the tags decide what the
baseline is worth. With none, `mix surfex.baseline` refuses, unless `--no-tags` says
you mean to baseline test versions alone and tag later at that per-tag cost. It ends by
reporting what it adopted: the trusted test versions, the `verifies` relations, and the
spec units left without one.

**What it is.** A record, per trusted test version, that the version counts as if it had
discriminated, plus that test's `verifies:` tags as relations with basis `baseline`.
`confirm --evidence` then carries the code each baselined test exercises (`implements`,
basis `baseline`). The note says why the suite is trusted; it stays in the log.

**What it isn't.**
- It isn't evidence: reports count baseline relations separately, naming the mode.
- It isn't repeatable: it is one-shot, so widening `adoption:` later trusts nothing new.
- It doesn't vouch for tests that aren't green at the time it is taken. Surfex refuses
  until they are.

## From trust to evidence

The baseline only shrinks. Each relation leaves it the first time its test
discriminates for real: a run that fails and then passes against different code, at the
same test version. `confirm --evidence` records that red→green, and the relation moves to
basis `evidence`. Ordinary bug-fix work does this over time. Nothing has to be scheduled.

When the backlog should end, `mix surfex.status --no-baseline` (or `baseline: :fail` in
`.surfex.exs`) fails while any relation still rests on the baseline.

## Code that deviates from the spec

A suite that passed green can still pass while the code deviates from the spec. Writing
the spec's tests turns those deviations up: the test is right, the code is wrong. Tag each
such test with the reference to what will fix the code, beside the skip that keeps the
suite green:

```elixir
@tag verifies: "free-over", deviation: "#119", skip: "known deviation (#119)"
test "delivery is free over the threshold" do
```

Record its `verifies` on its red run as usual. Status lists the unit under **Deviating**
with its reference, and its `proposed` relations don't fail. The gate can be joined while
the deviations are fixed. Completeness counts the unit incomplete (`deviates (#119)`), and
`RELATIONS.md` keeps the ledger. Run the deviation tests with their skips included now and
then (`mix surfex.test --deviations`, then `mix surfex.status --evidence`). A deviation
test that passes fails the status as stale. Meanwhile `mix surfex.confirm --evidence`
doesn't validate an `implements` to the deviating unit or to a section holding it: it
lists each as held back by the deviation, and validates it on the first run after the fix.
When the fix lands, drop the tag and the skip, and validate as for any change. A release
can hold every deviation with `mix surfex.status --no-deviations`.

## What changes cost afterwards

| Change | Trusted test | Re-evaluated test |
|---|---|---|
| Refactor the code, tests still green | `confirm --evidence` re-confirms it as `baseline`; no review | it needs a red→green, or a review (`mix surfex.validate`) |
| Edit the test | the new version isn't baselined: a red→green, or a review | the same |
| Change the spec unit | review the test against the new text, as always | the same |
| A test's first red→green | its relations move to `evidence` | the same |
| Narrow `adoption:` | its baseline relations are reported unvalidated: the backlog to review | — |
| Add a test | the normal process: fails first, then passes | the same |

Trust only saves work on the most common change, a refactor under green tests. Everything
else costs what it would without adoption.

## Moving to claim grain later

A baseline taken while relations sit on sections isn't redone when the project moves them
to its claims: `mix surfex.migrate` carries a section relation's baseline to a claim the
same baselined test verifies. See the guide "Migrating to claim grain".
