# Decisions: capture, review, govern

Record architectural decisions so the why survives the team. Review the candidates capture proposed, accept the ones that should govern, and keep them in git.

Decisions in repowise are linked to graph nodes, surfaced via
[`get_why`](https://docs.repowise.dev/mcp/get-why), and tracked for staleness as code
evolves.

There are two kinds of record and the difference matters. A **candidate**
is something capture extracted: from a commit message, an ADR file, a
`WHY:`/`DECISION:` marker, a PR body, an agent transcript. A candidate
governs nothing. A **decision** is a candidate a person or a signed agent
accepted with `repowise decision confirm`. Acceptance is the only thing
that turns one into the other; extraction, recurrence and confidence all
stop at the candidate.

```bash
repowise decision candidates          # the review queue
repowise decision confirm 9f3c --reason "..." --scope src/api
repowise decision list                # what governs
```

## Reviewing

### `repowise decision candidates`

List records awaiting review. Acceptable candidates come first, so the
top of the list is work you can finish in one pass. The rest name what
has to be filled in before `confirm` will take them.

```bash
repowise decision candidates [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--state` | string | `open` | open, accepted, merged, needs_split, dismissed, all |
| `--lane` | string |  | Only candidates raised by this extraction lane (pr, session, session_discovery, comment, git_archaeology, adr, inline_marker, conventions, cli) |
| `--limit` | number | `30` | Rows to print |

The `Acceptable` column is either `yes` or the same blockers `confirm`
would refuse with. Under `--format json` each row carries a `blockers`
array.

---

### `repowise decision confirm`

Accept candidates. This is the event that makes them govern.

```bash
repowise decision confirm DECISION_ID... [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--decision` | string |  | What was chosen, when the record does not say. Also corrects the stored record. |
| `--reason` | string |  | The rationale, or why the constraint needs none. Also corrects the stored record. |
| `--scope` | string |  | A file or module this governs. Repeatable; replaces the proposed scope. |
| `--evidence` | string |  | A commit, file or link the decision rests on. Repeatable. |
| `--as` | string |  | Record a different accepter than the repo's git identity. |
| `--agent` | string |  | Sign as this agent (e.g. claude_code) instead of as a person. Refused only when decision config agent-acceptance is off. |
| `--session` | string |  | The agent session signing. |
| `--preview` | boolean | `false` | Report what each id would do, and write nothing. |

Acceptance is refused rather than stored blank. A candidate needs
decision text, a reason, a scope and an evidence reference; the four flags
supply whatever is missing, and correcting them here corrects the record. Under
`--format json` the refusal is a document
(`{"error": "acceptance_refused", "blockers": [...]}`) and the exit code
is 1, so a scripted review can tell a refusal apart from a crash.

`confirm` takes one id or many, with the optional repository path still
last. Ids may be the 8-character prefixes `decision list` prints, as long
as the prefix is unique. Each id is applied independently: a batch that
refuses one commits the rest and exits 1. `--preview` puts every id
through the same acceptance contract and then rolls the whole run back,
so what it reports is what the write would have said.

```bash
repowise decision confirm 9f3c --reason "Postgres is the only store with the extension"
repowise decision confirm 9f3c 2b70 a114 --preview
repowise decision confirm 9f3c --scope packages/server --evidence 5a50232
```

One id emits the transition document those verbs always emitted
(`{"id", "status", "action"}`). Two or more, or `--preview`, emit a
results document with a `results` array plus `succeeded` and `failed`
counts.

---

### `repowise decision dismiss`

Tombstone candidates. They are kept as tombstones and never re-proposed,
so a reindex will not bring them back.

```bash
repowise decision dismiss DECISION_ID... [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--yes / -y` | boolean | `false` | Skip the confirmation prompt. |
| `--reason` | string |  | Why it was tombstoned. |
| `--agent` | string |  | Sign as this agent (e.g. claude_code) instead of as a person. |
| `--session` | string |  | The agent session signing. |
| `--preview` | boolean | `false` | Report what each id would do, and write nothing. |

Like `confirm`, it takes one id or many. `--format json` is
non-interactive by construction and skips the prompt, since a scripted
dismissal would otherwise read EOF and abort.

---

### `repowise decision merge`

Fold a candidate into an existing decision instead of accepting a
duplicate. The retired id keeps resolving through an alias, so anything
that wrote it down still works.

```bash
repowise decision merge DECISION_ID INTO_ID [PATH] [--agent SLUG] [--session ID]
```

---

### `repowise decision dedupe`

Fold candidates that duplicate another candidate into one record.
Evidence and governed files move to the surviving record, and every folded
id keeps resolving. Dry run by default.

```bash
repowise decision dedupe [PATH]            # show the plan
repowise decision dedupe --apply           # write it
```

`--tau` sets the similarity threshold (default `0.83`), `--limit` the
clusters listed, `--format table|json` the output.

---

### `repowise decision split`

Flag a candidate as bundling two choices. It never splits it for you; it
marks the record so a reviewer knows why it is stuck.

```bash
repowise decision split DECISION_ID [PATH] [--reason TEXT]
```

---

### `repowise decision status`

Report what decision capture did on the last run, and what it cost.

```bash
repowise decision status [PATH]
```

## Reading and writing records

### `repowise decision add`

Add a decision yourself, interactively or from flags. Prompts for title,
context, decision, rationale, alternatives, consequences, affected files,
and tags when the flags are absent. With both `--title` and `--decision` it
records without prompting and prints the new id, so an agent can call it. A
flag-driven record lands as `proposed`; the interactive prompts record
`active`.

```bash
repowise decision add [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--title` | string |  | Decision title (short) |
| `--context` | string |  | What forced this decision? |
| `--decision` | string |  | What was chosen? |
| `--rationale` | string |  | Why it was chosen |
| `--alternative` | string |  | A rejected alternative. Repeatable. |
| `--consequence` | string |  | A tradeoff accepted. Repeatable. |
| `--affects` | string |  | A file or module this governs. Repeatable. |
| `--tag` | string |  | A tag. Repeatable. |
| `--evidence-commit` | string |  | A commit this decision was made in. |
| `--kind` | string | `architectural` | architectural governs the code; agreement is a rule about how the work is done, names no file and is not checked against the code. |
| `--agent` | string |  | Record it as this agent's own proposal (source agent), e.g. claude_code. |
| `--session` | string |  | The agent session recording it. |
| `--format` | string | `table` | table or json |

`--agent` marks a candidate an agent reasoned out itself, and it ranks
beside session-mined candidates in the review queue. Unlike a person's
manual entry, accepting it needs an evidence reference (`--evidence-commit`
here, or `--evidence` on `confirm`).

```bash
repowise decision add --agent claude_code --title "One writer per store"   --decision "Only the pipeline writes the store" --rationale "..." --affects packages/core
```

---

### `repowise decision list`

List decision records. By default shows everything; flags filter the
view.

```bash
repowise decision list [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--status` | string | `all` | proposed, active, deprecated, superseded, dismissed, all |
| `--source` | string | `all` | Filter by capture source (adr, agent, cli, comment, commit, conventions, git_archaeology, inline_marker, llm_inferred, pr, session) |
| `--proposed` | boolean | `false` | Shortcut for --status proposed |
| `--stale-only` | boolean | `false` | Show only stale decisions |
| `--limit` | number | `100` | Max rows listed |
| `--all` | boolean | `false` | List every matching row |

Filters apply before the row cap. The table ends with `Showing N of M`, and
`--format json` carries `total` and `truncated`.

```bash
repowise decision list
repowise decision list --status active
repowise decision list --stale-only
```

---

### `repowise decision show`

Show full details of one decision. Accepts a unique id prefix.

```bash
repowise decision show DECISION_ID [PATH]
```

---

### `repowise decision deprecate`

Retire a decision, optionally naming the one that replaces it.
`--superseded-by` writes an explicit lineage edge and keeps the retired
id resolving.

```bash
repowise decision deprecate DECISION_ID [PATH] [OPTIONS]
```

| Name | Type | Default | Description |
|---|---|---|---|
| `--superseded-by` | string |  | ID of the decision that replaces this one. |
| `--agent` | string |  | Sign as this agent instead of as a person. |
| `--session` | string |  | The agent session signing. |

---

### `repowise decision health`

The dashboard view: stale decisions, candidates awaiting review,
ungoverned hotspots.

```bash
repowise decision health [PATH]
```

> **Note**
>
> The same data is available to your agent through `get_why()` with no
> arguments. That is the agent-facing equivalent of this command.

## The manifest

Accepted decisions can live in a tracked file, `.repowise/decisions.yaml`,
so they travel with the repo rather than with one machine's index.

### `repowise decision export`

Write accepted decisions to `.repowise/decisions.yaml`.

```bash
repowise decision export [PATH] [--force]
```

It refuses to write an empty file over a committed non-empty one.
Deleting the index is a documented recovery step and must not delete the
decisions along with the cache. Import them first, or pass `--force`.

---

### `repowise decision import`

Reconcile the store to `.repowise/decisions.yaml`.

```bash
repowise decision import [PATH] [--dry-run]
```

The file wins: it is what a colleague's commit changes, and the store is
the copy. Entries missing a reason or a scope are skipped rather than
guessed at.

---

### `repowise decision migrate`

Classify legacy rows written before candidates and decisions were
separate. Dry run unless you pass `--apply`.

```bash
repowise decision migrate [PATH] [--apply] [--limit N]
```

Records promoted by recurrence rather than by a person become candidates.
That is a visible loss of standing decisions, and it is the intended
outcome: they were never accepted. Nothing is deleted, every id keeps
resolving, and re-running changes nothing. `--limit` (default 10) caps
how many reasons the report lists.

## Capture policy

Which sources run, and whether any of them may call a model. These write
the `decisions:` block in `.repowise/config.yaml`; see
[Configuration](https://docs.repowise.dev/installation/configuration) for the schema. Every
mutating command takes `--dry-run`, and writes preserve every unrelated
key in the file.

### `repowise decision config`

```bash
repowise decision config show [PATH]
repowise decision config preset NAME [PATH] [--dry-run]
repowise decision config discovery [PATH] [OPTIONS]
repowise decision config capture-prompt --on|--off [PATH]
repowise decision config agent-acceptance --on|--off [PATH]
```

`capture-prompt` asks the agent, once per session, to record a decision
with `decision add --agent` after a commit whose message states one; it
only proposes. `agent-acceptance` lets an agent accept a decision, recorded
as the agent's with the session that signed, and the generated `CLAUDE.md`
marks it `[accepted by SLUG, not a person]`. Both are on by default; `--off`
keeps granting to people while agents still propose and withdraw.

`preset` takes one of `default`, `off`, `local_only`, `balanced`, `full`.

`discovery` sets the per-update budget for the one broad
session-discovery call. With neither budget flag it just prints the
resolved policy.

| Name | Type | Default | Description |
|---|---|---|---|
| `--max-sessions` | number | `12` | Session deltas one broad discovery call may read (1-24) |
| `--max-input-tokens` | number | `30000` | Input-token ceiling for one broad discovery call (2000-60000) |

---

### `repowise decision source`

```bash
repowise decision source list [PATH]
repowise decision source set SOURCE [PATH] --on | --off
repowise decision source set SOURCE [PATH] --llm | --no-llm
```

`source list` prints every source with its capabilities and current
state. `source set` needs at least one of the two switch pairs.
`--no-llm` keeps a source's deterministic parse and skips its model
stage, which only means something for a source that has both
(`inline_marker`, `adr`, `session`).

The switchable sources are `inline_marker`, `git_archaeology`, `adr`,
`pr`, `comment`, `session`, `session_discovery` and `conventions`.
Manual entry (`cli`) is an authority route rather than machine capture,
so it has nothing to switch off.

---

### `repowise decision llm`

```bash
repowise decision llm --on | --off [PATH] [--dry-run]
```

The master switch for decision-extraction model calls. Off is a complete
mode, not a degraded one: deterministic capture, transcript ingestion and
manual decisions all keep working, and already-accepted decisions keep
governing.
