overengineeringstudio / overengineeringstudio/effect-utils

fix(nix-cli): nix:hash misses staleness when upstream flake input rev changes without lockfile change

Open
#445 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:nix area:nix-hash origin:agent type:bug
Dominant language
TypeScript
Stars
82
Forks
2
Avg merge
1d 8h
Merged PRs (30d)
121

Description

Problem

The nix:hash task uses lockfileHash (SHA256 of pnpm-lock.yaml) as a fast staleness proxy. When an upstream flake input bumps its rev, mk-pnpm-cli build logic may change (e.g. different prepared install-tree structure from #410), producing a different pnpmDepsHashbut the downstream pnpm-lock.yaml doesn't change. The lockfileHash check passes, the full rebuild is skipped, and the stale hash persists.

Minimal reproduction

https://github.com/schickling-repros/2026-03-effect-utils-nix-hash-staleness

git clone https://github.com/schickling-repros/2026-03-effect-utils-nix-hash-staleness
cd 2026-03-effect-utils-nix-hash-staleness
bash repro.sh

Output:

=== Step 2: Simulate nix:hash staleness check (from nix-cli.nix) ===
  Stored lockfileHash:  sha256-KbJNMXX8ps/itgbCSyYR4wMAF895Ho60vW5Dhy14dCc=
  Current lockfileHash: sha256-KbJNMXX8ps/itgbCSyYR4wMAF895Ho60vW5Dhy14dCc=

  RESULT: lockfileHash matches → nix:hash considers hash UP TO DATE

  BUG: The pnpmDepsHash is actually STALE because effect-utils rev
       changed (aaaa111 → bbbb222), which alters mk-pnpm-cli build
       logic. But lockfileHash only fingerprints pnpm-lock.yaml,
       which didn't change.

Root cause

The lockfileHash fingerprint detects when pnpm-lock.yaml changes. But it doesn't detect when:

  • Upstream mk-pnpm-cli.nix / mk-pnpm-deps.nix build logic changes
  • Upstream workspace structure changes (new/removed packages in staged workspace)
  • Nix FOD inputs change due to flake input rev bumps

All of these alter the FOD output hash without touching pnpm-lock.yaml.

Affected repos

Any downstream repo with cliPackages entries using mk-pnpm-cli from effect-utils as a flake input.

Suggested fix

Option A: Include flake input revs in staleness fingerprint (recommended)

Extend the quick check to also fingerprint the resolved upstream rev from flake.lock or devenv.lock. If the upstream rev changed since the last nix:hash run, force a full rebuild.

Implementation sketch:

  • Add a flakeInputsHash field to the hashSource metadata
  • In update_fingerprint_hashes, compute a fingerprint of relevant flake input revs
  • In the quick check, compare stored vs current — if different, trigger full rebuild
Option B: Store upstream rev alongside pnpmDepsHash

Add an upstreamRev field to each cliPackages entry. The nix:hash task compares stored vs current and rebuilds when they differ.

Option C: Skip quick check in CI/automation context

Pass NIX_HASH_FORCE_REBUILD=1 to force nix:hash to always do the full build. Quick fix but doesn't address the general case.

Tradeoffs

  • A is the most principled — extends the existing fingerprint pattern, works for any upstream change
  • B is more explicit but requires downstream repos to maintain the rev field
  • C is the quickest fix, only works for automated runs

Filed by an automated assistant on behalf of @schickling

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with nix-cli.nix and the update_fingerprint_hashes logic described in the issue; inspect how flake.lock or devenv.lock input revisions could be included in the existing hashSource metadata. Use repro.sh to verify that changing an upstream revision triggers a full rebuild instead of accepting the stored pnpmDepsHash.

Written by the indexing model from the issue text.

Assessment

Domain
build-system, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.