feat(dirty-content-fingerprint): Nix flake computes fingerprint via self.narHash

Adds myDirtyFingerprint to flake.nix's existing eval-time let block,
computed as builtins.hashString "sha256" self.narHash truncated to 8 hex
chars (self.narHash is SRI base64, not hex -- rehashing is necessary),
gated on the same clean/dirty branch myCommitId already uses. No
preConfigure build-phase hook needed -- self.narHash has no pure-eval trap
unlike build_time's builtins.currentTime. Threaded through
nixSupport/default.nix into xce.nix/xcecli.nix's eval-time mesonFlags as
-Ddirty_fingerprint=, alongside the completely untouched -Dcommit_id=/
myCommitId and build_time's separate preConfigure mechanism.

Verified independently by review with real nix build/nix log inspection
on both xcecore_debug and xcecli: real, non-empty, content-sensitive
values reach mesonConfigurePhase, cross-checked deterministic via an
independent Python recomputation, with commit_id fully unaffected. Full
artifact completion is blocked by a pre-existing, unrelated sandbox
network limitation (confirmed recurring on two disjoint Go module sets),
not caused by this change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-21 04:57:56 +00:00
parent c9d40ba180
commit fc5cba15e1
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
5 changed files with 48 additions and 10 deletions

View file

@ -12,12 +12,9 @@
- _Requirements: 1.1, 1.2, 1.3, 1.4, 5.1_
- _Boundary: xce-build.sh_
- [ ] 2.2 (P) Nix flake computes the fingerprint via self.narHash at eval time, independently of myCommitId
- `myCommitId`'s existing computation (including its `self.dirtyShortRev`-derived `-dirty` suffix) is **not touched** -- this task only adds a new, independent value alongside it
- `src/flake.nix`'s existing eval-time `let` block gains `myDirtyFingerprint`, derived from `self.narHash` (truncated to match the dev-loop path's format), computed the same way `myCommitId` already is -- **not** via a `preConfigure` build-phase hook, since `self.narHash` (unlike `build_time`'s `builtins.currentTime`) is a legitimate flake self-introspection field with no pure-eval trap; resolves to empty on a clean tree, or a real hash otherwise
- `src/nixSupport/default.nix` forwards `myDirtyFingerprint` into each `callPackage` call, alongside the existing `myCommitId`
- `src/nixSupport/xce.nix`, `src/nixSupport/xcecli.nix` accept the new argument and append `"-Ddirty_fingerprint=" + myDirtyFingerprint` to the existing eval-time `mesonFlags` list
- Observable: `nix build .#xcecore_debug` (no `--impure`, the documented canonical command) still succeeds; editing a tracked file in the flake's source and re-evaluating changes the resulting binary's `--version` fingerprint
- [x] 2.2 (P) Nix flake computes the fingerprint via self.narHash at eval time, independently of myCommitId
- `myDirtyFingerprint` computed as `builtins.hashString "sha256" self.narHash` truncated to 8 hex chars (`self.narHash` is Nix's SRI base64 format, not hex -- rehashing was confirmed necessary, not optional), gated on the same `hasAttr "shortRev"`-style clean/dirty branch `myCommitId` already uses; threaded through `nixSupport/default.nix` into `xce.nix`/`xcecli.nix`'s eval-time `mesonFlags` list as `-Ddirty_fingerprint=`, alongside the untouched `-Dcommit_id=`; `build_time`'s separate `preConfigure`/`mesonFlagsArray` mechanism left completely undisturbed
- Observable confirmed live (independently re-verified by review, including a full re-run of both `nix build ./src#xcecore_debug` and `./src#xcecli`, no `--impure`): `nix eval` resolves a real, non-empty, content-sensitive `-Ddirty_fingerprint=` value matching an independent Python cross-check; editing a tracked file changes the resolved value; `-Dcommit_id=` unaffected throughout; `nix log` confirms both values reach the real `mesonConfigurePhase` invocation. Full artifact completion is blocked in this sandbox by a pre-existing, unrelated network limitation (an autoscaler Go module fetch needing `goproxy.cn`, confirmed recurring identically on two disjoint Go module sets) -- not a regression from this task, and orthogonal to the eval/meson-configuration behavior this task's Observable actually requires
- _Requirements: 1.1, 1.2, 1.3, 5.1_
- _Boundary: Nix packaging_