computeProfileRealizeKey hashed a recipe's dependency names but never
the versions actually resolved for them. Dependency resolution is
dynamic (an unpinned "openssl" resolves to whatever's newest in the
synced repo), so a repo sync that bumps a build-time dependency to a
new version was invisible to the cache: the key stayed identical and a
stale profile tree kept getting served indefinitely.
Added install.resolveDependencyTokens, a resolve-only counterpart to
installPackagesToProfile that mirrors its exact resolution behavior
(same constraint parsing, no preferred selections) without installing
anything. restoreOrInstallDependenciesToBuildProfile now resolves
before computing the cache key, and threads the resolved {name,
content_hash} pairs through computeProfileRealizeKey instead of the
raw dependency list. Reused the same RepoCache set for the subsequent
install on a cache miss, so this costs one extra local resolve pass
rather than a second repo sync.
Added a regression test proving the key changes when a dependency's
resolved content hash changes (and stays stable when it doesn't);
confirmed it fails without the fix.