The second half of #177. Landing a stack today cost over twenty job runs because every rebase gave each commit a new sha and the same tree, and dedupe keyed on the sha.
Builds record the commit's tree (migration 0045, builds.tree, indexed with
repo and job). When a push job is queued, a prior success for the same tree and
job stands for the new commit: it gets a ci/<job> success status naming the
build it came from, and no build is created. Push jobs only — scheduled and tag
builds carry no tree, since their trigger is the clock or the tag, and vuln in
particular must run against today's advisory database, not a cached verdict.
The existing sha-keyed skip stays and runs first; the tree lookup is the fallback for the rebase case.
TestQueueBranchBuildsSameTreeReusesSuccess makes two commits with one tree,
lets the first pass, and asserts the second queues nothing and carries the
success status. TestSuccessBuildForTree covers the lookup, including that an
empty tree never matches.
Closes #177