"Don't discover the wrong door at runtime. Ask both sides — what do you need, what can you do — before anything moves."
Turn a runtime surprise into a preflight decision
The Keychain story failed in the middle of the work, which is the worst place to find out an envelope can't do the job. The system-level fix is to make that mismatch impossible to discover mid-operation: check it before mutation, not during.
Executors declare what they can do
Every executor reports its capabilities as an explicit list: interactive_gui_session, login_keychain, ssh_credentials, sudo_noninteractive, user_approval_available, reboot_survivable, watchfire_callback. It's a self-description of which doors this executor actually is — not a guess, a declaration.
Steps declare what they require
Every operation step declares the capabilities it needs to succeed. Apply this OS update requires reboot_survivable, because it will restart the machine out from under any session. Read this token requires login_keychain. The requirement is part of the step's definition, sitting right next to what the step does.
Preflight matches the two
Before any mutation, preflight compares required against available. If the executor's envelope can satisfy the step, it runs. If it can't, the operation doesn't limp forward and hope — it moves the target to needs_attention, or delegates the same durable operation to a compatible executor. What it never does is loop credential prompts, copy secrets into the operation, or pretend that reaching the host implied it could do the work.