# Public API
## Candidate adapter
`Candidate` is the only adapter surface. It declares:
- `type Chat: Send + Sync + 'static;`
- `fn open(runtime: Arc<dyn Runtime>, initial_primary: String, llm: Arc<dyn Llm>) -> (Self::Chat, tokio::sync::mpsc::UnboundedReceiver<ChatEvent>);`
- `fn append(chat: &Self::Chat, text: String) -> impl Future<Output = Result<(), ChatError>> + Send;`
- `fn restart(chat: &Self::Chat) -> impl Future<Output = Result<(), ChatError>> + Send;`
- `fn view(chat: &Self::Chat) -> impl Future<Output = Result<ChatView, ChatError>> + Send;`
- `fn finalize(chat: Self::Chat) -> impl Future<Output = Result<ChatView, ChatError>> + Send + 'static;`
The signatures use the declarations from `kcode-k1-chat-core` directly. An implementation should only translate these operations to the candidate chat implementation.
## Verifiers
- `verify_initial_primary_delta_output_order_and_no_self_trigger::<C>()` proves initial-primary retention, empty-input rejection, exact per-object deltas, output-before-pending ordering, one text event, and absence of output-only inference.
- `verify_retry_schedule_stall_pending_and_fresh_restart::<C>()` proves five attempts, exact virtual 10/20/40/80-second retry boundaries, live attempts, same-object identical retry deltas, fifth-error stalling, pending accumulation, and a fresh full-primary restart.
- `verify_blocked_threads_are_independent::<C>()` proves that a gated inference in one chat does not impede another chat on the same current-thread executor.
- `verify_finalize_waits_closes_and_stalled_finalize_returns::<C>()` proves that finalization waits through queued and terminal tool results, closes events, and returns without waiting when already stalled.
- `verify_dropped_text_and_activity_receivers_stall_cleanly::<C>()` proves clean stalls after failed text or real activity delivery, completion of active tool work, and fresh-object restart deltas.
Each function is a one-shot synchronous verifier. It returns normally when the contract holds and otherwise panics at the failing operation or assertion. Each invocation creates one paused current-thread Tokio runtime, owns and releases its gates, finalizes its chats, and checks event-stream closure where applicable. Scripted models, runtime plans, updates, polling, settling, and clock control remain private.
Call verifiers from ordinary synchronous tests, not from inside an existing Tokio runtime. A valid consumer pattern is:
```rust
#[test]
fn chat_foundation_conformance() {
kcode_k1_chat_testkit::verify_initial_primary_delta_output_order_and_no_self_trigger::<MyCandidate>();
}
```
Every verifier performs a fixed number of scripted operations with bounded fixture state and fixed settling passes. Retry verification advances 150 seconds of paused virtual time and does not wait that duration in wall time. Work outside candidate operations is constant except for copying the short scripted strings; wall-clock completion still depends on the candidate making cooperative progress.