# Decisions

One input decided is a `Decision`. It is a union, narrowed by `outcome` and then by `reflex`. `decide` makes one.
`fill` answers an ask. `run` runs a chosen call. `handle` does all of it.

## `decide(input, { tags?, signal? })`

```ts
const d = await project.decide("kill the lights in the den", { tags: ["home"] })
```

Asks the adapter, reads its answers, and gates them. Runs nothing. `tags` offers only the reflexes carrying one
of them. `signal` aborts the adapter call, and `decide` rejects with the signal's own reason.

## The four shapes

| `outcome`   | Carries                                                                                           |
| :---------- | :------------------------------------------------------------------------------------------------ |
| `"run"`     | `reflex`, `args`, `values`, `call`, `effect`, `confidence`, `weakest`, `judgments`, `contenders`, `runner_up?`, `whole?` |
| `"confirm"` | All of the above, plus `prompt: { own, reason, template }` and `because: Cap[]`: every reason it stopped, in order |
| `"ask"`     | `reflex`, partial `args` and `values`, `unconsumed`, `missing: Missing[]`, and the judgments so far |
| `"abstain"` | `contenders`, the ranking, and `judgments`                                                        |

Every decision also carries three more things. `input` is the sentence as decided. `plan` is the digest it was
decided under. `trace` has one entry per adapter call: `{ adapter, questions, ms }`.

```ts
switch (d.outcome) {
  case "run":     await project.run(d); break
  case "confirm": if (await ui.confirm(d.prompt.template)) await project.run(d, { confirmed: true }); break
  case "ask":     project.fill(d, await ui.pick(d.missing)); break
  case "abstain": ui.say(d.contenders); break
}
```

## `args` and `values`

`args` is what the classifier read, typed: `{ type: "option", key }`, `{ type: "word", word, value? }`,
`{ type: "pick", span, value }`, `{ type: "flag" }`. `values` is what the body receives: the key, the word's
value or else the word, the number or text, `true`. With `Reflexes` from `evoke.d.ts`, or a manifest handed as
code, both are typed per reflex once `d.reflex` is known:

```ts
if (d.outcome === "run" && d.reflex === "lights") {
  d.values.room    // string
  d.values.state   // "on" | "off" | "dim"
}
```

An app that wants a reflex's wording with a body of its own calls `decide`, switches on `d.reflex`, and reads
`d.values`.

## Confirm

`prompt.own` is `evoke`'s line: the call, the effect and the weakest judgment. `prompt.reason` says in one
line why the call waits, a phrase for each cap, as the CLI prints it under the call. `prompt.template` is the
reflex's own question, filled in. `because` lists why it stopped: `destructive`,
`no_gate`, `under_floor`, `one_view`, `respelt`, `text_read`, `more`, `cut`, `quoted`, `text_left`, `whole`, `detail`,
`named`, `pointed` ([Outcomes](../use/outcomes.md#confirm)). A confirm decision runs only with
`run(d, { confirmed: true })`.

`decide` reads the input as one call. When its words say the call is wanted once more, like `too` or `the same
for`, the decision is a confirm with `more`, since there is no second step to be the other time. `steps` reads
every step of a sentence.

## Ask and `fill(d, given)`

`missing` says, per argument, its `ask`, why it is missing, and what it may be. Missing means never stated, or a
pick out of range. What it may be is the options, the vocabulary's words, or which recognizer reads it, with
`choices.recent` listing the values recalled from the results the application handed `decide`, `handle` or
`weave` as `recent: [{ reflex, data }]`, newest first, when the pick's manifest names the field. Where the
input's words say a pick's value aloud and read in more than one way, `words` holds them and `choices.readings`
lists what they read as: offer those in place of the recalled values. For a word from a vocabulary, `likely`
names the listed word to offer for a yes before the choices, which keep their order. `fill` takes what a person answered, by
argument name: an option's key, a word, or the text a pick reads, a recalled value or a reading among them. It
types the answer and gates again, synchronously:

```ts
const filled = project.fill(d, { room: "den" })       // a Decision again: run, confirm, or still an ask
```

A text that does not read is a `DiagnosticError` naming the argument and what it may be:
`room: "attic" is not one of den, office`. A flag is never asked.

## `run(d, { signal? })`

Runs the chosen call's body and resolves to `{ text, data? }`, with `contained` when a file or an argv ran:
whether this machine held it to its declaration, in the shape [`--json`](../reference/json.md#shape-by-outcome)
prints. A reflex handed as code runs in-process. A file runs in a
child. An argv is spawned. A body's failure is a `FailureError`. `signal` aborts the body, and `run`
rejects with the signal's reason. A decision made under another plan is refused as misuse, with a `TypeError`. A
reflex that takes an earlier step's whole result is refused with a `DiagnosticError`: only `weave` hands one, so
a host with its own loop learns at `run` that `decide`'s decision was a taker's. A playbook is refused the same
way, `<name> is a plan of steps; say it in a sentence`: only `steps` and `weave` make its plan.

## `handle(input, { confirm?, ask?, tags?, signal? })`

The whole loop: decide, then ask and fill until nothing is missing, then confirm, then run.

```ts
const handled = await project.handle(input, {
  confirm: d => ui.confirm(d.prompt.template),   // true runs, false declines
  ask: d => ui.pick(d.missing),                  // answers by name, or undefined to decline
})
```

| `handled.outcome` | When                                                                                          |
| :---------------- | :-------------------------------------------------------------------------------------------- |
| `"ran"`           | The body ran: `decision` and `result`                                                         |
| `"abstained"`     | `none` won, or the route was under its floor                                                  |
| `"declined"`      | `confirm` returned `false`, `ask` returned `undefined`, or an answer changed nothing           |
| `"unanswered"`    | A confirm or an ask was reached and no handler was given. The decision itself is the answer   |

An answer that does not read is asked again once. Twice is a decline. An empty input is refused before the
adapter is asked. A decided reflex that takes an earlier step's whole result is refused before any confirm, and
so is a playbook. Only a diagnostic, a fault or a failure throws.

## `steps(input, { tags?, signal? })` and `weave(input, { confirm?, ask?, proceed?, tags?, signal? })`

A sentence that asks for several things is a weave ([Weaving](../use/weaving.md)). `steps` reads one into its
plan, runs nothing, and returns it sealed as a plan file — the sentence, the plan, every answer the classifier
gave, and the pins it was decided under — the object `evoke try --save` writes and `evoke run <file>` reads
([The plan file](../reference/json.md#the-plan-file)):

```ts
const pinned = await project.steps("look up dana's address and email them")
const plan = pinned.weave
plan.steps       // [{ n: 1, text, decision, reflex: "contact", effect: "read", ... }, { n: 2, ... }]
plan.binds       // [{ from: 1, to: 2, arg: "to", field: "email", kind: "email", via: "fill" }]
plan.stages      // [[1], [2]]: a stage's steps run together; stages run in order
plan.verdict     // { outcome: "run" | "ask" | "confirm" | "refuse", because?: [...] }
pinned.set       // the plan digest it was decided over; pinned.answers, every answer the plan took
```

Each step carries its `decision`, the `Decision` `decide` would have made of its words alone; `shared` names
the words the sentence said once for several steps that reached it, `{ service: { word: "checkout", via:
"fill" } }`; `repair` says how a part that was not decided on its own became a step, `"narrowed"`, `"spliced"`,
`"merged"`, `"split"`, `"corrected"`, `"named"`, `"first"`, `"verb"`, `"again"` or `"apart"`
([The JSON line](../reference/json.md#shape-by-outcome)). A binding whose `via` is `"takes"` is a whole result by
the name its source returns, with no `kind`; a plan with no source for one, or two, has `verdict.outcome`
`"refuse"` and `no_source` or `several_sources` among its `because`. A step a playbook wrote carries `from`, the playbook, its step and the
slots the sentence filled ([Playbooks](../author/playbooks.md)); `folded` names the parts of the sentence that
repeat one of its steps; and the verdict's `because` holds `reviewed` per playbook, with the sentence's own
prompt. `steps(input, { ask })` answers a slot the sentence lacks before the plan is made, as `weave`'s `ask`
does; such a plan is a sheet, and `weave` refuses it as a file, since a file holds no one's answers. `weave`
settles what the plan asks first, then runs every step under `handle`'s handlers, each told which step and round
asks, a `Turn`:

```ts
const woven = await project.weave(input, {
  ask: (d, turn) => ui.pick(d.missing, turn.step),   // before anything runs, for a required argument no step provides
  confirm: (d, turn) => ui.confirm(d.prompt.template), // at the step's turn
  proceed: plan => ui.confirm("Run the plan as it stands?"),  // a step refers to another it takes nothing from
})
woven.status     // the worst step's: "ran", "failed", "declined", "refused", "unanswered"; or why nothing ran
woven.steps      // per step: { step, status, why?, bound, rounds: [{ round, input, decision, status, result? }] }
```

A `confirm` handler may wait: hand the decision, plain JSON, to a queue a second person reads, and resolve
with their answer; the weave goes on where it waited, and nothing that ran runs twice. The whole plan may travel
instead: `JSON.stringify(pinned)` is the file, and `weave(pinned, { proceed, confirm?, ask?, signal? })` runs it
on the same project, here or on another machine — its pins checked first, a `DiagnosticError` naming the first
that moved and the call that makes the plan again; the plan made again from the file's answers under its gate
and refused when it does not read the same; then `proceed(pinned)`, required whatever the verdict, since a
file's numbers are whoever wrote them; then every step under the handlers, a value bound at run time decided by
this project's adapter. A plan that asks or refuses runs nothing.

```ts
const checker = await load({ root, adapter: jev() })
const woven = await checker.weave(JSON.parse(file) as Pinned, {
  proceed: pinned => ui.confirm(`Run the plan of ${JSON.stringify(pinned.input)}?`),
  confirm: (d, turn) => ui.confirm(d.prompt.template),
})
``` A body's failure is the
step's, with `status: "failed"`, never a throw. A step after one that stopped is `skipped`, with `why: { type:
"earlier_step" }`. A step bound to a list of records runs once per record, one
round each. A step that takes whole results receives them in its body's `args`, handed by the weave alone; its
`bound` entries name each argument, its source and the name, with no `value`.

`signal` aborts the adapter's call while the plan is made, as it does in `decide`, and cancels the run once it
is under way: every body is ended, its own `signal` aborted first, nothing starts after, and every step that did
not finish reads `skipped` with `why: { type: "cancelled" }`. `weave` then rejects with the signal's reason, the
record on it as `woven`:

```ts
try {
  await project.weave(input, { signal: controller.signal })
} catch (error) {
  if (error === controller.signal.reason) console.log(error.woven.steps) // what ran, and what was cancelled
  else throw error
}
```

**Next:** [Adapters](adapters.md).
