Skip to content

fix(deps): a cold home can install gcc again, and CI can see it when it cannot (2026.8.10.2) - #526

Merged
Sunrisepeak merged 2 commits into
mainfrom
fix/cold-install-dep-resolution
Aug 10, 2026
Merged

fix(deps): a cold home can install gcc again, and CI can see it when it cannot (2026.8.10.2)#526
Sunrisepeak merged 2 commits into
mainfrom
fix/cold-install-dep-resolution

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Fixes #524. Ships the client half of #525's fix chain.

What happened

2026.8.10.1 began filling dependency_store_roots on every install, and shipped libxpkg 0.0.55 in the same release. Either alone is inert; together they executed a path where dep_install_dir gated on how specific the query was rather than on whether the answer was unique.

Six of the seven call sites in xim-pkgindex returned nil. gcc and meson could not install on any cold home — new machines, cold CI caches, fresh-install, and every downstream mcpp build. godot silently fell back to the host's GL; the graphics banner reported unknown.

The resolution fix is libxpkg 0.0.56 (openxlings/libxpkg#40). This PR takes that dependency, bumps the version, and adds the thing that was missing on this side: a way to notice.

Why CI could not see it

A warm home skips the install, so the config hook never runs. Every lane here stayed green while the released binary could not install a toolchain — the first detector was a downstream repo's cache miss.

E2E-79 is that detector, in-tree: a consumer declares a namespaced ranged coordinate, the resolver places the dependency, and the hook must find it on a genuinely cold home. Verified against both builds:

libxpkg 0.0.55  →  FAIL: consumer install failed (exit 1) -- this is #524
libxpkg 0.0.56  →  PASS: a config hook resolves its declared dependency on a cold home

It also pins the other half of the contract with a second consumer that asks for something it never declared: that must fail, name the coordinate, and say it is not a declared dependency. "Cannot answer" and "is not installed" produced the same nil for a whole release — that is what sent the bug report looking for a missing glibc that was sitting on disk.

Offline reproduction

.agents/tools/repro-dep-install-dir.sh replays all seven real call shapes against any libxpkg revision — no network, no install, no home touched.

$ .agents/tools/repro-dep-install-dir.sh            # 0.0.54 / 0.0.55 / 0.0.56
$ .agents/tools/repro-dep-install-dir.sh worktree   # uncommitted working tree

It takes worktree explicitly because every other form reads the file out of git, and an uncommitted fix otherwise tests as if it were not there — which reads as "my fix does nothing" rather than "I forgot to commit".

Documents

Release order

libxpkg 0.0.56 must be published before this merges — mcpp.lock's hash is recomputed from the published artifact.

Companion: openxlings/xim-pkgindex#589.

…it cannot (2026.8.10.2)

2026.8.10.1 began filling `dependency_store_roots` on every install, and
shipped libxpkg 0.0.55 in the same release. Either alone is inert; together
they executed a path where `dep_install_dir` gated on how specific the QUERY
was rather than on whether the ANSWER was unique. Six of the seven call sites
in xim-pkgindex returned nil: gcc and meson could not install on any cold home
-- new machines, cold CI caches, `fresh-install`, and every downstream mcpp
build -- while godot silently fell back to the host's GL and the graphics
banner reported `unknown`.

The fix is libxpkg 0.0.56 (`resolved_dep` judges ambiguity, which its own
uniqueness guard already decided, and matches the version half as the RANGE a
recipe actually writes). This commit takes that dependency and adds the thing
that was missing on this side: a way to notice.

**E2E-79, and why it has to be cold.** A warm home skips the install, so the
config hook never runs -- which is exactly why every lane here stayed green
while the released binary could not install a toolchain. The first detector
was a downstream repo's cache miss. This test is that detector, in-tree: a
consumer declares a namespaced ranged coordinate, the resolver places the
dependency, and the hook must find it. Verified against both builds -- it
fails on libxpkg 0.0.55 with "this is #524" and passes on 0.0.56.

It also pins the other half of the contract, with a second consumer that asks
for something it never declared: that must fail, name the coordinate, and say
it is not a declared dependency. "Cannot answer" and "is not installed" made
the same nil for a whole release, and that is what sent the bug report looking
for a missing glibc that was sitting on disk.

**`.agents/tools/repro-dep-install-dir.sh`** replays all seven real call
shapes against any libxpkg revision offline -- no network, no install, no home
touched. It reads the file out of git, and takes `worktree` for an
uncommitted one, because otherwise a fix that is not yet committed tests as if
it did not exist.

Root cause, blast radius and the #525 analysis:
`.agents/docs/2026-08-10-issue-524-525-root-cause-and-fix-design.md`
Task graph and cross-repo order:
`.agents/plans/2026-08-10-issue-524-525-implementation.md`

Refs #524, #525
… costs

The cross-build lane went red on main, not just here. mcpp 2026.8.10.1's host
toolchain post-install fixup binds `glibc@2.39` while the resolver installs
2.44 -- latest since xim-pkgindex#582 -- and refuses to fall back.

Established by re-running ONE unchanged run id across the index bump that made
mcpp 2026.8.10.1 latest (xim-pkgindex#588, 01:55Z): the same commit passed with
mcpp 2026.8.8.4 at 19:09 and failed with 2026.8.10.1 at 03:41. Same workflow,
same runner image. Also reproduces locally against UNMODIFIED libxpkg 0.0.55,
which is what rules out this branch as the cause.

Filed as mcpp-community/mcpp#406.

The pin is temporary and it is not free: this job takes the latest mcpp on
purpose, to be the canary for exactly this. Pinning it muzzles the canary, so
the comment names the removal condition rather than sitting there as an
unexplained version. Until #406 lands, breakage against the newest mcpp is
invisible on this lane.

Also adds the 2026.8.10.2 release notes.
@Sunrisepeak
Sunrisepeak merged commit 0bbf59b into main Aug 10, 2026
8 checks passed
@Sunrisepeak
Sunrisepeak deleted the fix/cold-install-dep-resolution branch August 10, 2026 04:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: 2026.8.10.1 冷装 xim:gcc@16.1.0 失败 —— 依赖解析到 glibc 2.44 但 gcc config hook 找不到 payload

1 participant