# Grok Lead Runtime Adapter

## Scope

This adapter maps neutral Okstra lead operations to the Grok CLI. Read it only when the rendered launch prompt selects `leadRuntime=grok`.

## Capability declaration

| Field | Value |
|---|---|
| `runtime` | `grok` |
| `leadRoleLabel` | `Grok lead` |
| `userPromptMode` | `native-question` |
| `workerDispatchBackend` | `mixed` |
| `initialPromptDeliveryMode` | `eager-include` |
| `sessionAccounting` | `artifact-only` |
| `resumeMode` | `native-session-id` |
| `teardownMode` | `process-cleanup` |
| `leadEventSource` | `lead-events-jsonl` |

## Wizard interaction relay

Read this contract when `okstra preflight` returns this file as `runtimeReadiness.relayContract`. The JSON is the complete interaction mapping for this host. `semanticFunctions` is an allowlist: the skill may declare a function only when both this list and the live harness expose it.

```json
{
  "schemaVersion": 1,
  "runtime": "grok",
  "semanticFunctions": [
    "plain_text_input",
    "native_single_select",
    "native_multi_select",
    "native_question_group"
  ],
  "nativeLimits": {
    "minOptions": 2,
    "maxOptions": 15,
    "maxQuestions": 8
  },
  "interactions": {
    "native-single": {
      "function": "ask_user_question",
      "input": {
        "callCount": 1,
        "questions": "one",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-label-description",
        "multiSelect": false
      },
      "response": {
        "envelope": "answers",
        "key": "rendered-question-text",
        "selection": "selected-label",
        "submit": "matching-option-value"
      }
    },
    "native-multi": {
      "function": "ask_user_question",
      "input": {
        "callCount": 1,
        "questions": "one",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-label-description",
        "multiSelect": true
      },
      "response": {
        "envelope": "answers",
        "key": "rendered-question-text",
        "selection": "selected-labels-joined-comma-space",
        "submit": "csv-matching-option-values-in-option-order"
      }
    },
    "native-group": {
      "function": "ask_user_question",
      "input": {
        "callCount": 1,
        "questions": "all-in-original-order",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-label-description",
        "multiSelect": "questions[].multi"
      },
      "response": {
        "envelope": "answers",
        "key": "rendered-question-text",
        "selection": "selected-label-or-labels-joined-comma-space",
        "multiValue": "csv-matching-option-values-in-option-order",
        "submit": "compact-step-json-values"
      }
    },
    "numbered-single": {
      "function": "host-text",
      "input": {
        "questions": "one",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-numbered-markdown-label-and-description"
      },
      "response": { "source": "next-message", "submit": "raw" }
    },
    "numbered-multi": {
      "function": "host-text",
      "input": {
        "questions": "one",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-numbered-markdown-label-and-description"
      },
      "response": { "source": "next-message", "submit": "raw" }
    },
    "sequential-group": {
      "function": "host-text",
      "input": {
        "questions": "all-one-at-a-time-in-original-order",
        "question": "label-with-progress",
        "options": "all-in-original-order-as-numbered-markdown-label-and-description"
      },
      "response": {
        "source": "next-message-by-question-position",
        "submit": "compact-step-json-raw"
      }
    },
    "plain-text": {
      "function": "host-text",
      "input": { "questions": "one", "question": "label-with-progress" },
      "response": { "source": "next-message", "submit": "raw" }
    }
  }
}
```

For `ask_user_question`, map each wizard option to the tool's `{label, description}` input without removing, shortening, or reordering entries. Do not send `preview`. Look up each answer by the exact rendered `question` string sent to the tool, including the progress suffix. A single-select answer is the selected label. A multi-select answer is one string whose selected labels are joined with `, `. Match those labels back to the complete original option list, emit their `value` fields in original option order, and join the values with `,` for the wizard. Native plans are emitted only when the prompt fits `nativeLimits` (unique option labels, two to fifteen options, one to eight questions); other prompts use the text mapping so no option is dropped. The host adds a free-text row on every question. Do not drop a wizard option to make room for it. If the user types in that row and the text matches no option label, submit the typed text unchanged. For a group, key the compact JSON object by the corresponding `questions[].step`; a multi-select question stores its ordered value CSV as one string, not a JSON array.

For a `host-text` mapping, render each numbered item as its option label followed by its description verbatim; preserve every item and its order. The next user message is the raw answer. Do not translate numbers, CSV members, labels, or values before `okstra wizard step`. A sequential group wraps each raw reply in one compact JSON object keyed by `questions[].step`; the wizard owns normalization.

## Semantic operation mapping

| Operation | Mapping |
|---|---|
| `read_artifacts` | Read the manifest-provided paths through the current Grok host file interface. |
| `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
| `prompt_user` | Use `ask_user_question` for approvals and clarifications that fit `nativeLimits`. Do not print a numbered list in chat while that tool is available. Do not infer an answer from silence. |
| `dispatch_worker` | Verify the materialized invocation. Use the host primitive with `promptPath` and `hostModelValue` for `native-session`; use deterministic `okstra worker-dispatch` with `modelExecutionValue` for `cli-wrapper`. **Not in a cmux run:** the cmux adapter overrides this row. |
| `await_workers` | Await through the selected common dispatch backend, then verify terminal state and Result Paths. |
| `redispatch_worker` | Start a fresh attempt from the persisted assignment and record the supplied dispatch kind. |
| `shutdown_workers` | Clean up only host or process resources owned by this run. |
| `record_lead_event` | Append progress and activity records to the manifest-provided `leadEventsPath`. Emit the matching `PROGRESS:` line and, when an activity record is required, the immediately following `ACTIVITY:` line from the same structured fields. |
| `collect_usage` | Return explicit unavailable lead usage until Grok registers a session transcript or CLI usage artifact contract. |

## Completion, cleanup, and resume

- Do not infer the current host from an installed `grok` executable. The runtime must come from an explicit request or current-session declaration.
- Keep persisted provider, model, runner, and dispatch-kind assignments unchanged.
- Before a native call, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`; after the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting it. This is a verified specification link, not proof of delivered prompt bytes.
- Resume with the persisted Grok session ID when one exists; otherwise resume from Okstra run artifacts.
