anyhow at the public boundary left library consumers unable to match
on failure modes: every mistake was an opaque error, and the ones
worth branching on (host prerequisites, unsupported architectures)
could only be recognized by string matching.
Public functions now return Result<T, ecr::Error> (thiserror) with
semantic variants for those conditions: user namespaces unavailable,
binfmt_misc unregistered, architecture not served by the registry,
missing subuid/subgid entry. anyhow stays the internal error type;
everything else converts to Error::Other, which transparently wraps
the full context chain. Errors raised inside the namespace child
cross the process boundary as formatted chains and also surface as
Other; the error pipe wraps them in anyhow before formatting so the
chain still survives. The CLI maps the error back into anyhow, so
its output is unchanged.