Every terminal result separates the answer intended for a person from status and structured application data. In Kestrel 0.8, the readable answer is always available as assistantText: string | null.
Protocol layers
The 0.8 protocol defines execution, durable conversations, events, exact approvals, policy-owned recovery, and Mission Control. These layers share identity and correlation but retain separate authority and persistence rules.
type RunnerTerminalResult = {
output: NormalizedOutput;
assistantText: string | null;
finalizedPayload?: unknown;
operatorAffordance?: unknown;
};Read each field
| Field | Meaning |
|---|---|
output | Runtime status, run identity, final step, checkpoint, quality, and wait state |
assistantText | Non-empty human-facing assistant text, or null when no assistant message exists |
finalizedPayload | Optional structured data; it does not own display text |
operatorAffordance | Optional control state for a waiting or completed run |
Add an assistant message to the interface only when assistantText is non-null. Handle finalizedPayload separately so invalid structured data cannot erase or replace a valid answer.
Keep four concerns separate
assistantTextis what a person may read as the assistant response.outputdescribes runtime status and normalized execution data.finalizedPayloadcarries optional application-specific structured data.- The terminal event type distinguishes completed, failed, and cancelled outcomes; waiting information explains how paused work may continue.
const result = terminal.payload.result;
if (result.assistantText !== null) {
appendAssistantMessage(result.assistantText);
}
persistRunOutcome({
type: terminal.type,
output: result.output,
finalizedPayload: result.finalizedPayload,
});Waiting and recovery
A waiting result names the exact pending request. Recovery choices carry stable option identifiers and review context. Resume the same session and bind the reply to both the pending request and, when present, recoveryOptionId; descriptive labels alone are not authority.
External approvals
An approval authorizes one canonical action and effect under an actor, scope, and expiry. Validate it immediately before execution and record both the approval decision and effect result.
Mission Control
Use mission_control.project.get to inspect project work, attempts, evidence, review, and acceptance. Execute a typed change through mission_control.action.execute. Runtime control remains responsible for an active or waiting run.
Compatibility
Runtime, Protocol, SDK, adapters, and clients must follow their declared exact dependency contracts; compatible packages do not need equal semantic versions. Kestrel does not add a 0.7 wire or API shim around removed project actions.