Declare your tool's lifecycle once. Whippletree compiles it into the native format of all four harnesses, and tells you what each will enforce.
Whippletree probes the harness you have installed and reports the tier every requirement reaches, before it places anything on that harness.
$ whippletree preflight ./my-tool --target codex
whippletree preflight · target codex (probed 0.146.0)
stop-gate want ≥T1 got T1 SATISFY native Stop + stop_hook_active
session-start-signal want ≥T2 got T1 SATISFY native SessionStart
file-read-signal want ≥T4 got T2 SATISFY matcher Bash|Edit|Write|apply_patch;
misses reads in pipelines and heredocs
bin-reachable want ≥T1 got T1 SATISFY bundle channel
Plan: 4 satisfy, 0 degrade, 0 refuse.
A requirement lands where the harness can carry it. When the harness cannot meet a hard requirement at its declared tier, Whippletree refuses to install rather than degrading the guarantee without saying so.
NativePreflight names a mechanism that meets the requirement outright, with nothing standing in for it.
DegradedA coarser mechanism stands in for the requirement, and preflight prints what the stand-in misses.
Compiled to instructionsBest-effort, no harness-level enforcement: the model is instructed to run the step and usually will, but can skip it under pressure.
ObserverReserved. Not implemented.