Trial
0016. /mistral command family: show, set, test
Trial
- Status: Trial
- Date: 2026-02-14
Context
Section titled “Context”The config layer (ADR
0010) is strictly validated
and layered (project JSON > user JSON > env > defaults), but inspecting it
means reading the file by hand, and setting a value means hand-editing JSON
with no feedback. The config-UX research recommended a small command family
as the top improvement: a status card showing where every effective value
comes from, a set that writes safely, and a live connectivity check.
Two forces shape the write side. First, a trust boundary: the project-scope
file .pi/mistral-native.json is part of the repository (it travels with
commits and reviews), so a command silently writing it would let a local
command mutate what every contributor sees — it stays hand-authored. Second,
ADR 0004’s
env-first default: no file must ever be created speculatively, or the
out-of-the-box behavior stops being “no config, just env”.
Decision
Section titled “Decision”Add a /mistral command family (registered by the extension, implemented
in extensions/mistral/commands.ts), three subcommands:
/mistral(bare): a status card listing every behavioral key’s effective value with its provenance — which layer supplied it (project file <path>,user file <path>,env <VAR>,default,unset) — plus the config paths in the chain and the auth source label (never the key value). Values using the config-value protocol display the raw stored string, never the resolved one./mistral set <key> <value>: writes user scope only — the first existing file in the user chain, else the chain head, created on firstset(never speculatively). Atomic (temp file + rename in the same directory), merge-preserving (other keys survive), validated viavalidateMistralFileConfigbefore the write, and write-then-verified by re-reading the chain. Unknown keys andmodels.rateCard(nested object array, no sane single-string encoding) get a Usage error pointing at the documented keys and the file for hand-editing. (User scope stays the default;/mistral set --projectwrites the project scope — ADR 0022 supersedes the user-scope-only rule forset.)/mistral test: a liveGET /v1/modelscheck with a named failing step (auth / network / HTTP status) and a concrete fix hint per failure.
Invariants the command layer commits to:
- File-as-truth, no shadow state: commands re-read the user and project
scopes at invocation time via the pure loaders — never the module-level
session_startsnapshot (getEffectiveMistralConfig) and never the test override. Only a successfulsetcallsrefreshMistralConfigto sync the live session; a bare status read never mutates cached state. - Project scope is read-only for commands:
setrefuses to write it and the card says so when a project key shadows a user key (superseded forsetby ADR 0022). - No speculative file creation: the user file is created only by an
explicit first
set(extending ADR 0010’s “authored by hand” note). - Never render secrets: the API key is never displayed; auth shows the source label only.
- Non-TUI degradation: output rides
ctx.ui.notifyonly — it works in TUI and RPC modes; pi binds no UI context in print/json modes, so the command is silent there by pi’s own contract (no separate plain print channel in v1).
Consequences
Section titled “Consequences”Easier: one command answers “why is this value active?”; setting a key is safe, validated, and idempotent-by-value; connectivity failures name their step instead of a bare status code.
Given up / accepted: set covers single-string keys only (nested
models.rateCard stays hand-edited; the Usage error says so); env values
set through pi’s provider-scoped options.env are invisible to the card
(it reports process env — the same documented limitation as the region
notice, ADR 0012); other concurrent pi sessions pick up a written value at
their next session_start. The write is same-directory-rename atomic but
does not preserve the target’s file mode (same trade-off as the login
region write).