fix(docker/tui): tolerate npm's peer-flag drop in lockfile comparison#19520
Merged
Conversation
`_tui_need_npm_install()` compares the canonical `package-lock.json` against
the hidden `node_modules/.package-lock.json` to decide whether `npm install`
needs to re-run. npm 9 drops the `"peer": true` field from the hidden lock
on dev-deps that are *also* declared as peers (the canonical lock preserves
the dual annotation). That made the check flag 16 packages (`@babel/core`,
`@types/node`, `@types/react`, `@typescript-eslint/*`, `react`, `vite`,
`tsx`, `typescript`, …) as mismatched on every launch, triggering a runtime
`npm install`.
Inside the Docker image, that runtime install then fails with EACCES because
`/opt/hermes/ui-tui/node_modules/` is root-owned from build time, so
`docker run … hermes-agent --tui` prints:
Installing TUI dependencies…
npm install failed.
…and exits 1, with no preview. The empty preview is a second bug: the
launcher captured only stderr, but npm 9 writes EACCES to stdout, which
was DEVNULL'd.
Fixes:
- Add `"peer"` to `_NPM_LOCK_RUNTIME_KEYS` so the comparison ignores the
non-deterministic field, alongside the existing `"ideallyInert"`.
- Capture stdout as well as stderr in the install subprocess so future
failures surface a useful preview instead of a bare "failed." line.
Regression tests:
- `test_no_install_when_only_peer_annotation_differs` — the exact scenario
- `test_install_when_version_differs_even_with_peer_drop` — guards against
the peer-drop tolerance masking a real version skew
On-host impact: the same false-positive was firing on every `hermes --tui`
invocation from a normal checkout, silently running a no-op `npm install`
each time (it converged because the host's `node_modules/` is writable).
Startup time on the TUI should drop noticeably.
jsboige
pushed a commit
to jsboige/hermes-agent
that referenced
this pull request
May 14, 2026
fix(docker/tui): tolerate npm's peer-flag drop in lockfile comparison
dannyJ848
pushed a commit
to dannyJ848/hermes-agent
that referenced
this pull request
May 17, 2026
fix(docker/tui): tolerate npm's peer-flag drop in lockfile comparison
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
fix(docker/tui): tolerate npm's peer-flag drop in lockfile comparison
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
fix(docker/tui): tolerate npm's peer-flag drop in lockfile comparison
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_tui_need_npm_install()compares the canonicalpackage-lock.jsonagainst the hiddennode_modules/.package-lock.jsonto decide whethernpm installneeds to re-run. npm 9 drops the"peer": truefield from the hidden lock on dev-deps that are also declared as peers (the canonical lock preserves the dual annotation). That made the check flag 16 packages (@babel/core,@types/node,@types/react,@typescript-eslint/*,react,vite,tsx,typescript, …) as mismatched on every launch, triggering a runtimenpm install.Inside the Docker image, that runtime install then fails with EACCES because
/opt/hermes/ui-tui/node_modules/is root-owned from build time, sodocker run … hermes-agent --tuiprints:Installing TUI dependencies…
npm install failed.
…and exits 1, with no preview. The empty preview is a second bug: the launcher captured only stderr, but npm 9 writes EACCES to stdout, which was DEVNULL'd.
Fixes:
"peer"to_NPM_LOCK_RUNTIME_KEYSso the comparison ignores the non-deterministic field, alongside the existing"ideallyInert".test_no_install_when_only_peer_annotation_differs— the exact scenariotest_install_when_version_differs_even_with_peer_drop— guards against the peer-drop tolerance masking a real version skew On-host impact: the same false-positive was firing on everyhermes --tuiinvocation from a normal checkout, silently running a no-opnpm installeach time (it converged because the host'snode_modules/is writable). Startup time on the TUI should drop noticeably.