Preflight
Preflight is how Pretorin verifies that the host is connected to the sources a framework needs before evidence work begins. The platform recommends canonical source kinds per framework, but it cannot verify whether any of them are reachable from where you are working — only the CLI host can. Preflight is that CLI-local verification layer, and its verdict is the single source of truth for source availability (it replaces the platform connection registry).
The model
A recommended source kind (e.g. code_repository, cloud_control_plane)
maps to a collection of resolvers, not a single one. Each resolver is a
concrete, host-local way to reach part of the evidence story:
Resolver type | Verifies | Example params |
|---|---|---|
workspace_path | a path (and optional marker) exists | {path: /infra, marker: "*.tf"} |
cli_tool | a CLI is present/authenticated | {name: gh, probe: "gh auth status"} |
command | a generic probe exits 0 | {probe: "curl -fsS https://host/health"} |
manual / attested | nothing — user-asserted | {identity: "SOC2-2026-Q1"} |
mcp / connected_api / pretorin_feature | a declared probe, else unverified | {probe: "..."} |
Resolver type and params are open — custom types work, and an unknown
type with a declared probe is simply run (the registry fails open). A resolver
may also declare capabilities, matched against a recipe’s
requires.sources[].capabilities so the executor requires only the resolver(s)
a recipe touches.
Status vocabulary
Each resolver verifies to one of: connected (machine-verified), degraded
(reachable but stale/partial), missing (probe ran, not reachable), attested
(user-asserted, never silently “connected”), or unverified (no probe yet).
These roll up per kind:
ready— every bound resolver is up; the whole evidence story is reachable.degraded— some up, some not; partial story.missing— resolvers bound and verified, none reachable.unverified— resolvers bound but not probed yet.unmapped— a recommended kind with no resolvers bound.
Two grains of availability
- Control grain — the per-kind rollup answers “is the whole evidence story present?”
- Executor grain —
start_recipeonly requires the specific resolver(s) a recipe touches (kind + optional capability), so a degraded kind never blocks a recipe that doesn’t need the down resolver.
How availability is decided
The verdict drives every availability decision:
list_recipes/ the capture plan hide recipes whose required kinds are verified missing; unmapped/unverified kinds fail open (shown asunknown— a soft “verify before capture”, never a hard “not connected”).start_reciperefuses to open a context when a required kind is verified missing, unless you passforce=true.
Commands
pretorin preflight show # read the verdict for the active scope
pretorin preflight verify # probe every bound resolver, refresh status
pretorin preflight bind <kind> --type <type> [--param k=v ...] \
[--probe "<cmd>"] [--capability <cap> ...] [--recommended]
--system / --framework default to the active context
(pretorin context set). The agent-facing MCP tools are get_preflight,
verify_preflight, and update_preflight.
The guided workflow
For an interactive, recommendation-aware setup, run the preflight
workflow: it pulls the framework’s recommended source kinds, diffs them
against what you have mapped, walks you through binding a resolver collection
for each gap, verifies them, and reports ready / degraded / missing. The
artifact persists locally per (system, framework) under
~/.pretorin/preflight/, so later evidence work reads the verdict directly —
re-run pretorin preflight verify if it has gone stale.