# Change evidence: changes, check, suspects, report, events

Change Records rebuilt from git with an evidence checklist, plus repowise check for change policy, suspects for a symptom, evidence reports and events.

Every `init` and `update` reads each first-parent commit of HEAD as one
**Change Record**: a PR, MR, Gerrit change or lone commit, identified by its
forge number, then its `Change-Id`, then its sha. The commands on this page
read those records. None of them calls a model, and missing evidence is
reported as `unknown`, never as a failure.

| Command | What it answers |
|---|---|
| `changes list / show / export` | What merged, and the evidence behind each change |
| `check` | Does this change meet the rules in `.repowise/policies.yaml` |
| `suspects` | Which recent changes to read first for a symptom |
| `report assessment / changes / inventory` | An evidence pack to hand to someone else |
| `events` | What moved between two index runs, per component |

## `repowise changes`

```bash
repowise changes list [OPTIONS]
repowise changes show REF [OPTIONS]
repowise changes export [OPTIONS]
```

`show` takes an id (`pr-123`, `change-I...`, `commit-<sha>`), the forge ref
`list` prints, or any commit sha the change landed. It prints the record with
its **evidence checklist**: components touched, declared owners, suggested
reviewers, reaching tests (measured or inferred), contracts and consumers in
other repositories, decisions crossed, health delta, AI provenance with
coverage, the diff size rank and outcomes. Each item has a status (`ok`,
`attention`, `unknown`), the basis it rests on and its source. The checklist
is built on first read and kept.

**Outcomes** come from explicit links only: a later revert, a later fix that
names the change as its cause in its own words (`Fixes: <sha>`, "regression
in"), and how many of its files received fixes within 30 days
(`changes.outcome_fix_days`).

| Name | Type | Default | Description |
|---|---|---|---|
| `list --category` | string |  | Only this category (feature, fix, ...). |
| `list --shape` | string |  | merge, squash or commit. |
| `list --grep` | string |  | Substring of the title, id or a file path. |
| `list --needs-attention` | boolean | `false` | Only changes whose kept checklist flags attention. Builds no checklist. |
| `list --limit / --offset` | number | `30 / 0` | Page through the list (limit 1 to 1000). |
| `show --format` | string | `table` | table, json (the native record) or in-toto (an in-toto Statement v1 whose subjects are the commits). |
| `show --evidence / --no-evidence` | boolean | `evidence` | Include the evidence checklist. |
| `show --refresh` | boolean | `false` | Rebuild the checklist. |
| `export --since / --until` | string |  | Merge window in UTC (YYYY-MM-DD or ISO time). --until is exclusive. |
| `export --format` | string | `json` | json (JSON Lines, one record per line) or csv (one row per change and item). |
| `export --refresh` | boolean | `false` | Rebuild every checklist in the window. |
| `--path` | string |  | Repo path (defaults to cwd). All three subcommands. |

```bash
repowise changes list --category fix --limit 10
repowise changes show pr-412
repowise changes show 3f9c2ab --format in-toto > change.intoto.json
repowise changes export --since 2026-07-01 --until 2026-10-01 --format csv > q3.csv
```

`export` builds any missing checklist first, a few at a time (about 3 s per
change on a mid-size repository), and kept checklists are read back at no
cost. Progress goes to stderr. The same record is served by
`get_change_risk(include=["evidence"])` and
`get_context(targets=["change:<id>"])`.

---

## `repowise check`

Evaluate the change policy in `.repowise/policies.yaml` against a change.
Rules match components by name, tag or criticality, test conditions on
attribution, agent tier, reaching tests, contract breaks, decisions crossed
and bus factor, and take one action: `warn`, `require_owner_review`,
`require_tests` or `fail`. A rule can also wrap the `security`, `coverage`,
`doc_drift` or `health` gate. The file format is on
[Configuration](https://docs.repowise.dev/installation/configuration#repowisepoliciesyaml).

```bash
repowise check [REVSPEC] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `REVSPEC` | string |  | origin/main...HEAD, base..head or one commit. Default: the CI pull request's target...HEAD, else the remote's default branch...HEAD. |
| `--policies` | string | `.repowise/policies.yaml` | Policy file to evaluate. |
| `--sarif-file` | string |  | Also write SARIF 2.1.0 here, for code scanning or reviewdog. |
| `--junit-file` | string |  | Also write JUnit XML here, for a CI test report. |
| `--format` | string | `table` | table, json, sarif or junit. json carries the change's evidence too, usable as OPA input. |
| `--path` | string |  | A path inside the repository (defaults to cwd). |

```bash
repowise check origin/main...HEAD
repowise check --sarif-file check.sarif --junit-file check.xml
repowise check --format json > check.json   # opa eval --input check.json ...
```

| Exit | Meaning |
|---|---|
| `0` | No `fail` rule fired. `warn`, `require_owner_review` and `require_tests` are reported, never fatal |
| `1` | A `fail` rule fired |
| `2` | The policy is invalid (every problem listed), or a `fail` gate could not be evaluated |

A condition whose evidence is unavailable (no index, attribution off) leaves
its rule **not evaluated**, and it never fires. Without a policy file, `check`
reports nothing to evaluate.

---

## `repowise suspects`

Rank the changes merged in a window against a symptom: an issue's text, an
error message, a stack trace or a list of files. Text match, import distance,
co-change, recency and stack-trace hits are combined by reciprocal rank
fusion, and each row lists the signals that fired with their evidence.

```bash
repowise suspects [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--symptom` | string |  | What was seen: an issue's text or an error message (read up to 20,000 characters). |
| `--files` | string |  | A file the symptom involves. Repeatable, up to 50. |
| `--trace` | string |  | A file holding a stack trace. |
| `--since` | string | `14 days before --until` | Merged on or after (UTC). |
| `--until` | string | `now` | Merged before (UTC): when the symptom was seen. |
| `--limit` | number | `10` | Rows to show (1 to 200). |
| `--format` | string | `table` | table or json |
| `--path` | string |  | Repo path (defaults to cwd). |

```bash
repowise suspects --symptom "TypeError: cannot read properties of undefined (reading 'id')"
repowise suspects --trace crash.txt --since 2026-09-01
repowise suspects --files src/billing/invoice.ts --format json
```

The output is a reading order, not a verdict. A change outside the list is
not cleared, so widen `--since` for a regression that surfaced late, and
confirm a suspect with `git bisect run`. Also served as
`POST /api/repos/{id}/suspects`, `get_context(include=["suspects"])` and a
chat tool.

---

## `repowise report`

Evidence documents built from the index, for a repository or every repository
of a workspace. JSON is canonical; Markdown, self-contained HTML and CSV
render the same content, and local paths are removed. Missing evidence is
reported as unresolved, never as a low score.

| Subcommand | Contents |
|---|---|
| `assessment` | Components and their posture, hotspots, bus factor, dead code by tier, test reach, contracts, governing decisions, outcomes, provenance coverage and a same-stamp trend. Each item in OpenSSF Scorecard check shape plus `method` and `basis` |
| `changes` | For every change merged in a period: components and owning teams, review record, reaching tests, the policy verdict, provenance and outcomes, with a period summary and a method appendix stating what git cannot attest |
| `inventory` | Components with their owner teams, languages, entry points and packages |
| `estate` | A workspace's repositories and services, system map and architecture with their evidence, contracts and calls that reached no provider, health and churn per repo, riskiest seams and where to start |

```bash
repowise report assessment [PATH] [OPTIONS]
repowise report changes [PATH] [OPTIONS]
repowise report inventory [PATH] [OPTIONS]
repowise report estate [PATH] [--sections IDS] [--format FORMAT] [--out FILE]
```

`estate` needs a workspace (`.repowise-workspace.yaml`) and takes no
`--workspace` or `--repo`. See [Evidence reports](https://docs.repowise.dev/intelligence/evidence-reports#the-estate-report)
for its sections.

| Name | Type | Default | Description |
|---|---|---|---|
| `--format` | string | `markdown` | json, markdown, html or csv, or a renderer a plugin registers. |
| `--out` | string |  | Write to this file. |
| `--workspace / --no-workspace` | boolean |  | Cover every workspace repo, or force single-repo mode. |
| `--repo` | string |  | Workspace repo alias to cover. |
| `assessment --sections` | string |  | Comma-separated section ids, e.g. components,hotspots,bus-factor. |
| `changes --since` | string | `90 days before the newest indexed commit` | Merged on or after this date (UTC). all covers every indexed change. |
| `changes --until` | string |  | Merged before this date (UTC). |
| `changes --refresh` | boolean | `false` | Rebuild every checklist in the period. |
| `changes --no-build` | boolean | `false` | Report kept checklists only and count the rest as unknown. |

```bash
repowise report assessment --format html --out assessment.html
repowise report changes --since 2026-07-01 --until 2026-10-01 --format markdown --out q3-changes.md
repowise report changes --since all --format json --out changes.json
repowise report inventory --workspace --format csv --out inventory.csv
```

Reports describe code and components, not people: reviewers and owners are
counted, never named or ranked. Git records no review, so the review record
reads "not recorded in git" unless `Approved-by` trailers or a plugin's
change-metadata source supply one.

---

## `repowise events`

Typed events between consecutive index runs. Each `init` and `update` stores
a snapshot of every component, and what moved since the previous run under
the same analyzer stamp is stored as an event, written to
`.repowise/events.jsonl` as CloudEvents 1.0.2.

```bash
repowise events [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--since` | string |  | Only events from then on: 7d, 12h or an ISO date. |
| `--kind` | string |  | Only this kind. Repeatable. |
| `--limit` | number | `200` | Most events to print (1 to 10000). |
| `--format` | string | `table` | table, json or jsonl |
| `--path` | string |  | Repo path (defaults to cwd). |

| Kind | Fires when |
|---|---|
| `ownership_shift` / `owner_inactive` | Recent activity moves between owners, or a declared owner goes quiet |
| `bus_factor_drop` | A critical component's bus factor falls |
| `new_hotspot` | A file becomes a hotspot (off by default) |
| `contract_added` / `contract_broken` | A provided contract appears or breaks (workspace only) |
| `decision_stale` | A governing decision goes stale |
| `dead_code_growth` / `test_reach_drop` | Dead code grows, or test reach drops |

```bash
repowise events --since 7d
repowise events --kind bus_factor_drop --format jsonl
```

Each kind is switched under `events.kinds` in
[Configuration](https://docs.repowise.dev/installation/configuration#the-events-block). The
Commits page in the web UI lists the same events in its Events view.
