# Reviewing a change

When an agent hands you a change, you should see it in the order it
matters. `jadpo approval --before <ref>` writes a report in that order, as
Markdown and JSON in `build/review/`, and a static web view of the same
report:

What [a first record holds](/docs/comparing-two-builds.md#what-a-first-record-holds)
that a person decides comes before all of it, under "Decisions compared with
nothing": each thing `jadpo check` couldn't compare, in plain words, with where
it shows. A project's first public write, and the first personal data anyone may
read, lead the report this way.

1. **Decisions that need a person.** Each change that needs an acceptance,
   a file in `acceptances/` in which a person accepts it
   ([Acceptances](/docs/acceptances.md)). Each is said in
   plain words, who can now do what to which data ("`CompanyRole.viewer`
   can now read `work.Project.budget`"), with whether its acceptance file
   exists: `acceptance missing`, `reason missing` while one lists it with
   no `///` reason yet, or `accepted`, with the reason.
2. **Paths.** Under each decision, the path that makes it true: actor →
   route → action or query → field → output. A path starts only with
   callers who can take it: `anyone` only through a route anyone may call,
   and a query or action listed under `actions:` only for those on its line
   ([Listing a query](/docs/action-permissions.md#listing-a-query)). A decision with no
   such way says none was found; the source and the records still hold it.
3. **Newly reachable code.** Declarations that didn't change but are now
   reached from a new place, which a line diff never shows.
4. **Other behaviour.** Changes to the
   [public API record](/docs/the-public-api-record.md), the schema and
   [migrations](/docs/migrations.md), failures, events and subscribers,
   integrations, and the differences in the
   [permissions report](/docs/the-permissions-report.md), as
   `access.jadpo_record` holds it, and the
   [personal-data report](/docs/the-personal-data-report.md). A
   record's changes are shown as a diff of its entries, and the report's a
   connection at a time, from the before side's. Beside them: what
   widens access with no grant changed, an output gaining a field or an
   action reading or writing another entity; every
   [decline](/docs/declining-a-judgement-call.md)
   the change adds or edits, with its reason; each prompt that changed; the
   imported types and the calls that ship unreviewed or unconfirmed
   ([Mapping imported types](/docs/where-packages-come-from.md#mapping-imported-types-to-standard-types));
   and [wording not yet accepted](/docs/reviewing-a-change.md#wording-not-yet-accepted).
5. **Source,** grouped by declaration rather than by file, by domain, each
   with whether it was added, changed or removed and where it is.

The terminal says the decisions in full, with each one's first path, and
counts the rest. Exit code 0 means the report was written, whatever it
says: `jadpo check` is what fails until each decision has its acceptance.

```text
$ jadpo approval --before main
1 decision needs a person
◆ `CompanyRole.viewer` can now read `work.Project.budget`     acceptance missing
    CompanyRole.viewer → GET /projects/{id} → work.project_detail
      → ProjectView.budget

1 declaration newly reachable
  budgets.convert_currency  now reached from GET /projects/{id}

  before    main at 1a2b3c4
  api       1 route added
  schema    1 migration added
  access    1 field's grants changed
  source    6 declarations in 4 files

✓ Wrote build/review/approval.md

◆ decision  1 change waits for a person's acceptance
  next      A person accepts them: `jadpo acceptance new <purpose>` writes the
            draft for them. (human)
```

With `--json`, `data` holds the same report as `build/review/approval.json`
and the `file` it was written to. A source with errors writes no report:
what changed can only be worked out from a source that reads
(`approval not written`, with each error). An argument, a `--before` git
doesn't know, or nothing to compare with is
[`cli.approval_arguments`](/docs/errors/cli.approval_arguments.md); a base the
clone doesn't hold is
[`acceptance.base_missing`](/docs/errors/acceptance.base_missing.md). With nothing
to compare with but something
[a first record holds](/docs/comparing-two-builds.md#what-a-first-record-holds),
the report is written and holds that alone, saying why: there is no before side
to take a difference of. `before.not_judged_because` in the JSON says the same.

## Packages and services that need a person

Packages add their own decisions to the first section, each needing a
person's acceptance:

- A third party's package installed from git rather than the registry. It
  is marked **unverified** until a person accepts it.
- A **package's service** whose image is new or changed, shown with its
  image, digest and the hosts it asks to reach. It never starts until
  accepted.
- A new outside host a service is allowed to reach.
- A connection that receives personal data but can't erase it
  ([Erasure at providers](/docs/erasure-at-providers.md)).
- Bot checks allowed to pass when their provider is down
  ([Bot protection](/docs/bot-protection.md)).

## Wording not yet accepted

With `translations: { review: TranslationReview.required }`, wording that
changed and hasn't been accepted with
`jadpo translations accept <locale>` is listed under other behaviour too
([Tooling for translations](/docs/tooling-for-translations.md)).

## The web view

The web view adds what text can't: the graph of the change, the
differences between an agent's successive revisions of it, each path opened
to see what surrounds it, and links from every line to its source. It is a file in `build/review/`, which you open
on your machine or CI publishes beside the pull request. It holds no
accounts and records no approvals. Acceptances stay files, reviewed on the
git host like any other change.
