# okstra-user-response AI Manual

## Sources

- Skill source: [`skills/okstra-user-response/SKILL.md`](../../../skills/okstra-user-response/SKILL.md)
- Response core: [`scripts/okstra_ctl/user_response.py`](../../../scripts/okstra_ctl/user_response.py)
- Node wrapper: [`src/commands/inspect/user-response.mts`](../../../src/commands/inspect/user-response.mts)

## Purpose

`okstra-user-response` answers unresolved `C-*` clarification items and records explicit plan decisions without hand-editing a report or sidecar. The user selects or writes every answer. Publication changes only the user-owned `runs/<task-type>/user-responses/` sidecar.

The model-facing reads are fixed text. Do not use the automation-compatible JSON reads to drive a conversation. Do not open the final-report record directly.

| Command | Purpose |
|---|---|
| `okstra user-response list-view --home <home> --project <projectId> --limit 3` | List tasks that still need clarification answers or a plan decision. |
| `okstra user-response show-view --report <reportPath> --project-root <projectRoot>` | Show open questions, choices, impact, why asked, linked plan items, cited artifacts, approval context, plan candidates, and current state after validating project ownership. |
| `okstra user-response begin --report <reportPath> --task-key <taskKey>` | Open a typed transaction and return an opaque id. |
| `okstra user-response answer ...` | Add one validated answer to the draft. |
| `okstra user-response plan-decision ...` | Record an explicit plan decision. |
| `okstra user-response legacy-report-authoring ...` | Record contract 2.0 report-authoring permission. |
| `okstra user-response finalize --transaction <transaction>` | Merge and atomically publish the sidecar. |

The legacy `list` and `show` JSON commands remain for automation compatibility. They are not model-facing reads.

## Flow

1. Run `okstra preflight --runtime <host-runtime>` for the current harness. On `Okstra preflight: failed`, show `Reason` and `Recovery`, then stop. On `Okstra preflight: ready`, carry `Project root`, `Project ID`, `Runtime`, and `Relay contract`, then run `okstra paths --field home`.
2. Read the relay `Wizard interaction relay` JSON. When `native-single` is available and the option count fits `nativeLimits`, call `interactions.native-single.function` (`AskUserQuestion` / `ask_user_question` / `request_user_input` from that field). Do not print a numbered list in chat while the native tool is available. Otherwise render a numbered Markdown list. Do not substitute one host function name for another. Copy the view's `Picker:` `- Label:` / `Description:` pairs into that function in that order. Do not rebuild labels from the `Options:` dump. `--option-number` is the 1-based `Option N:` index, which is the same order as `Picker:`. The HTML report's `<select>` uses the same `option.answer` values. Pass only the `list-view` `Picker:` rows, the report `Picker:` rows, or the two confirmation labels. Do not append `Enter directly`. Claude Other, Grok `z`, and Codex's free-form row are `Enters an answer`; on a numbered list, so is a next message that is not a listed label or its 1-based number. Do not ask a second question for the custom value.
3. Select a task from `list-view` through that host picker. A host free-text row or unmatched next message is the report path or task key.
4. Read only `show-view --report <reportPath> --project-root <projectRoot>` for report facts. The view also prints `Why asked`, `Linked plan items`, and `Cited artifacts`.
5. Read every cited `path:line` under the project root and every linked plan-item definition before asking. Do not search beyond that list. Investigation explains; it never changes `options[]`.
6. Ask one open clarification at a time in the user's language through the host picker. The question body is why, what is already decided, the fork, and what stays blocked. Do not lead with `Kind`, `Blocks`, `Expected form`, or `C-NNN`. Keep the row id in parentheses at the end.
7. Echo the complete response and confirm through the host picker (`Record as shown` / `Change an answer`). Do not ask them to type `confirmed`.
8. Begin the transaction, add answers and decisions, then finalize it.

Each `options[]` row displays `{role, answer, rationale, scopeImpact, addedWork, directionChange, disposition}`. Contract 3.0 additionally displays `reach`, `scopeEffects`, and row-level `approvalContext`. Option descriptions use this order: If you pick this (`addedWork`). What it reverses (`directionChange`). Scope (`reach` or `scopeImpact`). Why it is on the board (`rationale`). If the view says `not stated in the report`, repeat that text and never invent a value. A quote from a cited file may follow those axes; it does not replace them.

When the user selects a predefined option, pass only the fixed view's one-based option number. Python resolves that option's `disposition`, answer, reach, and scope effects from the validated report:

```bash
okstra user-response answer --transaction <transaction> --clarification-id <C-NNN> --kind <kind> --option-number <N>
```

Every value, rationale, and reason body file must be a regular file under `<projectRoot>/.okstra/tmp/user-response/`; external files and symbolic links are rejected. For direct input, write the user's exact words there and use the mutually exclusive direct form:

```bash
okstra user-response answer --transaction <transaction> --clarification-id <C-NNN> --kind <kind> --disposition <answer|reframe> --value-file <value.md> [--rationale-file <rationale.md>]
```

Record a plan decision only when the user states it explicitly. Any reason file stays in that same temporary directory:

```bash
okstra user-response plan-decision --transaction <transaction> --status approved [--implementation-option <candidate-name>]
okstra user-response plan-decision --transaction <transaction> --status <revision-requested|rejected> --reason-file <reason.md>
```

The implementation option must match a candidate printed by `show-view`. A report with no open clarification can still require this decision.

Contract 2.0 alone supports legacy report-authoring permission. Its reason file stays in that same temporary directory:

```bash
okstra user-response legacy-report-authoring --transaction <transaction> --status <approved|denied> --reason-file <reason.md>
```

Finish with:

```bash
okstra user-response finalize --transaction <transaction>
```

Do not decode the transaction id. Do not inspect transaction state. Do not hand-edit report records, rendered reports, or sidecars.
