The job emitter resolves a dependency chain in several rounds in memory,
but a job's `if:` reads its needs' results from the database, where a
need skipped or failed earlier in the same pass was still blocked. A job
with `if: always() && needs.build.result == 'skipped'` was therefore
skipped instead of started.
Finished statuses are now persisted at the end of each round, which also
replaces the separate handling of skipped and failed reusable workflow
callers.