Skip to content

fix(config/reader): don't warn when packageManager and devEngines.packageManager match#12287

Merged
zkochan merged 2 commits into
pnpm:mainfrom
spencerbeggs:fix/silence-conflict-warnings-with-same-hash
Jun 16, 2026
Merged

fix(config/reader): don't warn when packageManager and devEngines.packageManager match#12287
zkochan merged 2 commits into
pnpm:mainfrom
spencerbeggs:fix/silence-conflict-warnings-with-same-hash

Conversation

@spencerbeggs

@spencerbeggs spencerbeggs commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

When package.json sets both packageManager and devEngines.packageManager to the same pnpm version with the same integrity hash pnpm prints a spurious warning on every command. For example, a package.json file that looks like:

{
	"packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
	"devEngines": {
		"packageManager": {
			"name": "pnpm",
			"version": "11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
			"onFail": "ignore"
		},
		"runtime": [
			{
				"name": "node",
				"version": "26.3.0",
				"onFail": "ignore"
			}
		]
	}
}

Issues a warning on every pnpm command:

Cannot use both "packageManager" and "devEngines.packageManager" in package.json. "packageManager" will be ignored.

Root cause

getWantedPackageManager compares the two fields to decide whether to warn, but the two sides were normalized differently:

  • parsePackageManager strips the integrity hash from the legacy packageManager field → 11.5.1
  • the devEngines.packageManager version was compared with its hash intact11.5.1+sha512.93f7b57…

So, "11.5.1" !== "11.5.1+sha512…" was always true and the warning fired, even for identical specs. An earlier fix in #11307 only suppressed the warning when neither side carried a hash.

Fix

parsePackageManager now also returns the hash (via a shared splitPackageManagerVersion), and getPackageManagerConflictWarning compares the fields structurally. The warning is suppressed only when the two specifiers are identical (name + version + hash, both-absent counts as equal):

name version hash result
same same both absent, or both present & equal ✅ no warning
same same present on one side only ⚠️ generic "Cannot use both…"
same same both present & differ ⚠️ "…contradictory integrity hashes"
same differ ⚠️ "…different versions of pnpm"
differ ⚠️ "…different package managers"

A hash on only one side is still a divergence — dropping the ignored packageManager field would lose that hash — so it warns with the original generic message. Two contradictory hashes for one version (a likely wrong-hash mistake) get a dedicated message. The generic single message is otherwise replaced by one tailored to each conflict, each ending with "packageManager" will be ignored.

Closes #12028.

Summary by CodeRabbit

  • Bug Fixes

    • Eliminated false conflict warnings when packageManager and devEngines.packageManager specify the same manager, version, and integrity hash.
    • Enhanced conflict messaging to clearly indicate whether a mismatch is due to different package manager names, versions, or integrity hashes.
  • Tests

    • Added/updated Jest coverage for warning scenarios across matching and mismatching name, version, and integrity-hash cases, plus parsing behavior.
  • Documentation

    • Updated the changelog to reflect the new, more precise warning behavior and conditions.

@spencerbeggs spencerbeggs requested a review from zkochan as a code owner June 9, 2026 16:13
Copilot AI review requested due to automatic review settings June 9, 2026 16:13
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 9, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0)

Grey Divider


Remediation recommended

1. Unsanitized warning values 🐞 Bug ⛨ Security
Description
getPackageManagerConflictWarning interpolates package.json-controlled values
(legacy.name/devEngines.name/legacy.version) directly into warning text that pnpm prints to stderr
without stripping control characters. A malicious repository can embed ANSI escape sequences or
newlines in those fields to forge/mislead terminal or CI log output when the conflict warning is
emitted.
Code

config/reader/src/index.ts[R903-925]

+function getPackageManagerConflictWarning (legacy: ParsedPackageManager, devEngines: ParsedPackageManager): string | undefined {
+  const ignoredSuffix = '. "packageManager" will be ignored'
+  const genericWarning = `Cannot use both "packageManager" and "devEngines.packageManager" in package.json${ignoredSuffix}`
+  if (legacy.name !== devEngines.name) {
+    return `"packageManager" (${legacy.name}) and "devEngines.packageManager" (${devEngines.name}) specify different package managers in package.json${ignoredSuffix}`
+  }
+  if (legacy.version !== devEngines.version) {
+    // "different versions" only makes sense when both sides are concrete
+    // versions. If one side has no semver version — e.g. the legacy field is a
+    // URL or a bare name — fall back to the generic notice rather than claiming
+    // a version mismatch.
+    if (legacy.version == null || devEngines.version == null) return genericWarning
+    return `"packageManager" and "devEngines.packageManager" specify different versions of ${legacy.name} in package.json${ignoredSuffix}`
 }
+  if (legacy.hash !== devEngines.hash) {
+    // Same name and version, but the integrity hashes differ. Two distinct
+    // hashes for one version is a likely wrong-hash mistake, so call it out
+    // specifically; a hash on only one side is a softer mismatch (the version
+    // still agrees) and gets the generic notice.
+    if (legacy.hash != null && devEngines.hash != null) {
+      return `"packageManager" and "devEngines.packageManager" specify ${legacy.name}@${legacy.version} with different integrity hashes in package.json${ignoredSuffix}`
+    }
+    return genericWarning
Evidence
The new warning messages interpolate manifest-derived fields directly into strings, and pnpm prints
these warnings to stderr via console.warn after adding a chalk prefix, without sanitizing the
message body.

config/reader/src/index.ts[903-927]
pnpm/src/getConfig.ts[24-40]
cli/default-reporter/src/reporterForClient/utils/formatWarn.ts[3-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getPackageManagerConflictWarning()` embeds `legacy.name`, `devEngines.name`, and `legacy.version` (read from `package.json`) into human-facing warning strings. These strings are printed to stderr with no sanitization, so control characters (e.g. ANSI escape sequences) or newline characters can be injected into logs/terminals.
### Issue Context
Warnings are rendered with a chalk prefix but the message body is emitted verbatim.
### Fix Focus Areas
- config/reader/src/index.ts[903-925]
### Suggested fix
- Introduce a small helper (local to `getPackageManagerConflictWarning` or nearby) that converts user-controlled fields to a safe, single-line representation before interpolation.
- At minimum: strip VT/ANSI control characters (e.g. `stripVTControlCharacters` from `node:util`) and replace `\r`/`\n` with escaped sequences or spaces.
- Apply the helper to `legacy.name`, `devEngines.name`, and `legacy.version` in all returned warning strings.
### Acceptance criteria
- Conflict warnings remain semantically the same for normal inputs.
- Inputs containing control characters/newlines do not cause multi-line output or terminal escape injection.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit 125c2e5

Results up to commit d784ac7


🐞 Bugs (1) 📘 Rule violations (0)


Remediation recommended
1. Unsanitized warning values 🐞 Bug ⛨ Security
Description
getPackageManagerConflictWarning interpolates package.json-controlled values
(legacy.name/devEngines.name/legacy.version) directly into warning text that pnpm prints to stderr
without stripping control characters. A malicious repository can embed ANSI escape sequences or
newlines in those fields to forge/mislead terminal or CI log output when the conflict warning is
emitted.
Code

config/reader/src/index.ts[R903-925]

+function getPackageManagerConflictWarning (legacy: ParsedPackageManager, devEngines: ParsedPackageManager): string | undefined {
+  const ignoredSuffix = '. "packageManager" will be ignored'
+  const genericWarning = `Cannot use both "packageManager" and "devEngines.packageManager" in package.json${ignoredSuffix}`
+  if (legacy.name !== devEngines.name) {
+    return `"packageManager" (${legacy.name}) and "devEngines.packageManager" (${devEngines.name}) specify different package managers in package.json${ignoredSuffix}`
+  }
+  if (legacy.version !== devEngines.version) {
+    // "different versions" only makes sense when both sides are concrete
+    // versions. If one side has no semver version — e.g. the legacy field is a
+    // URL or a bare name — fall back to the generic notice rather than claiming
+    // a version mismatch.
+    if (legacy.version == null || devEngines.version == null) return genericWarning
+    return `"packageManager" and "devEngines.packageManager" specify different versions of ${legacy.name} in package.json${ignoredSuffix}`
  }
+  if (legacy.hash !== devEngines.hash) {
+    // Same name and version, but the integrity hashes differ. Two distinct
+    // hashes for one version is a likely wrong-hash mistake, so call it out
+    // specifically; a hash on only one side is a softer mismatch (the version
+    // still agrees) and gets the generic notice.
+    if (legacy.hash != null && devEngines.hash != null) {
+      return `"packageManager" and "devEngines.packageManager" specify ${legacy.name}@${legacy.version} with different integrity hashes in package.json${ignoredSuffix}`
+    }
+    return genericWarning
Evidence
The new warning messages interpolate manifest-derived fields directly into strings, and pnpm prints
these warnings to stderr via console.warn after adding a chalk prefix, without sanitizing the
message body.

config/reader/src/index.ts[903-927]
pnpm/src/getConfig.ts[24-40]
cli/default-reporter/src/reporterForClient/utils/formatWarn.ts[3-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`getPackageManagerConflictWarning()` embeds `legacy.name`, `devEngines.name`, and `legacy.version` (read from `package.json`) into human-facing warning strings. These strings are printed to stderr with no sanitization, so control characters (e.g. ANSI escape sequences) or newline characters can be injected into logs/terminals.

### Issue Context
Warnings are rendered with a chalk prefix but the message body is emitted verbatim.

### Fix Focus Areas
- config/reader/src/index.ts[903-925]

### Suggested fix
- Introduce a small helper (local to `getPackageManagerConflictWarning` or nearby) that converts user-controlled fields to a safe, single-line representation before interpolation.
 - At minimum: strip VT/ANSI control characters (e.g. `stripVTControlCharacters` from `node:util`) and replace `\r`/`\n` with escaped sequences or spaces.
- Apply the helper to `legacy.name`, `devEngines.name`, and `legacy.version` in all returned warning strings.

### Acceptance criteria
- Conflict warnings remain semantically the same for normal inputs.
- Inputs containing control characters/newlines do not cause multi-line output or terminal escape injection.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit f363f62


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Results up to commit 7010003


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Results up to commit f782957


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Results up to commit 3301ab5


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Qodo Logo

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Parses packageManager specifiers including semver build-metadata hashes and compares name, version, and hash to emit precise warnings only for true divergences between packageManager and devEngines.packageManager.

Changes

Hash-aware packageManager conflict detection

Layer / File(s) Summary
Hash-aware packageManager parsing and conflict helpers
config/reader/src/index.ts
Adds exported ParsedPackageManager, splitPackageManagerVersion, updates parsePackageManager to return { name, version, hash }, and updates getPackageManagerConflictWarning and getWantedPackageManager to compare name, version, and integrity hash and produce specific diagnostics.
Config reader unit tests for hash and conflict scenarios
config/reader/test/index.ts
Adds tests and helpers exercising warnings for identical specifiers (including matching hashes), partial/contradictory hashes, non-concrete inputs, version mismatches, and package manager name mismatches; also adds parsePackageManager parsing tests.
pnpm integration tests for packageManager conflict handling
pnpm/test/packageManagerCheck.test.ts
Updates and adds end-to-end tests asserting no warning for same-version+same-hash, warnings for different hashes or asymmetric hashes, and updated expectations for name/version conflicts.
Changeset documentation
.changeset/devengines-package-manager-same-hash.md
Documents suppression of the prior false warning when both fields pin the same package manager with identical integrity hashes and clarifies that divergence warnings now state the specific reason (name, version, or hash mismatch).

Sequence Diagram

sequenceDiagram
  participant ConfigReader as Config Reader
  participant Parser as parsePackageManager
  participant Splitter as splitPackageManagerVersion
  participant Detector as getPackageManagerConflictWarning
  participant Warnings as warnings

  ConfigReader->>Parser: parse legacy `packageManager` spec
  Parser->>Splitter: split version and +hash
  Splitter-->>Parser: return name, version, hash
  ConfigReader->>Parser: parse `devEngines.packageManager` spec
  ConfigReader->>Detector: pass legacyParsed, devEnginesParsed
  Detector->>Detector: compare name, version, hash
  alt identical name+version+hash
    Detector-->>Warnings: no warning
  else name mismatch
    Detector-->>Warnings: "specify different package managers"
  else version mismatch
    Detector-->>Warnings: "specify different versions of pnpm"
  else hash mismatch
    Detector-->>Warnings: "different integrity hashes"
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • zkochan

Poem

🐰 I hop through specs with careful art,
I split the version and the hash apart,
When name, version, and hash all align,
No needless warning will you find,
Only true mismatches get my bark.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: preventing spurious warnings when packageManager and devEngines.packageManager match with identical integrity hashes.
Linked Issues check ✅ Passed The PR fully addresses issue #12028 by making parsePackageManager return hash values and comparing name, version, and hash structurally to suppress warnings only when all three match.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the packageManager/devEngines.packageManager conflict warning logic as described in issue #12028.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates pnpm/config-reader to treat packageManager and devEngines.packageManager as identical when they pin the same PM version including the same integrity hash, and improves the resulting conflict warnings.

Changes:

  • Preserve/compare the integrity hash (semver build metadata) when parsing packageManager references.
  • Emit more specific conflict warnings (different package manager vs different version vs different hash).
  • Expand CLI/config-reader test coverage for the new warning behaviors.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
pnpm/test/packageManagerCheck.test.ts Updates/adds CLI tests for new warning strings and hash-aware matching.
config/reader/test/index.ts Adds config-reader tests covering hash-aware equality and the new specific warning messages.
config/reader/src/index.ts Adds hash-aware parsing and introduces getPackageManagerConflictWarning to generate specific warnings.
.changeset/devengines-package-manager-same-hash.md Documents the behavior change and its motivation for a patch release.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread config/reader/src/index.ts Outdated
Comment thread pnpm/test/packageManagerCheck.test.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix spurious packageManager/devEngines.packageManager warnings when hashes match
🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

Walkthroughs

Description
• Parse and compare package manager version *and* integrity hash to avoid false conflict warnings.
• Emit more specific conflict warnings for differing managers, versions, or contradictory hashes.
• Add unit/integration tests and a changeset covering the new warning behavior.
Diagram
graph TD
  U["pnpm command"] --> R["getWantedPackageManager()"]
  R --> A["parsePackageManager()"] --> S["splitPackageManagerVersion()"] --> W["getPackageManagerConflictWarning()"] --> O["warnings (or none)"]
  R --> B["parseDevEnginesPackageManager()"] --> W
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Normalize both specs by stripping build metadata (hash)
  • ➕ Simpler comparison logic; fewer message variants.
  • ➖ Would hide meaningful divergence when one side includes a hash and the other doesn’t.
  • ➖ Would miss the dedicated 'contradictory hashes' case, reducing diagnostic value.
2. Compare the raw strings for equality (no structured parse)
  • ➕ Minimal code changes; preserves exactness.
  • ➖ Harder to produce targeted warnings (manager/version/hash).
  • ➖ Brittle around formatting differences or future schema tweaks.

Recommendation: Keep the PR’s structured comparison (name + semver part + optional hash). It fixes the false-positive warning while preserving safety (warn on any divergence) and improves UX via specific diagnostics for manager/version/hash mismatches.

Grey Divider

File Changes

Bug fix (1)
index.ts Compare package manager specs structurally (including integrity hash) +58/-10

Compare package manager specs structurally (including integrity hash)

• Extends parsePackageManager to retain semver build metadata as an integrity hash and factors out splitPackageManagerVersion. Adds getPackageManagerConflictWarning to suppress warnings only on exact matches and to emit more specific warnings for different managers, versions, or contradictory hashes.

config/reader/src/index.ts


Tests (2)
index.ts Add unit coverage for packageManager/devEngines conflict warnings +63/-0

Add unit coverage for packageManager/devEngines conflict warnings

• Adds a focused test suite covering no-warning scenarios (including matching hashes) and the three warning categories: generic hash-present-on-one-side, contradictory hashes, version mismatch, and manager mismatch.

config/reader/test/index.ts


packageManagerCheck.test.ts Expand integration tests for hash-aware conflict warnings +60/-3

Expand integration tests for hash-aware conflict warnings

• Updates existing assertions to match the new, more specific warning text and adds integration coverage for matching hashes, contradictory hashes, and hash-only-on-legacy scenarios.

pnpm/test/packageManagerCheck.test.ts


Documentation (1)
devengines-package-manager-same-hash.md Add changeset documenting hash-aware warning suppression +8/-0

Add changeset documenting hash-aware warning suppression

• Introduces a patch changeset for @pnpm/config.reader and pnpm describing the removal of spurious warnings when both fields match including integrity hash, and outlining the remaining divergence cases.

.changeset/devengines-package-manager-same-hash.md


Grey Divider

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/reader/src/index.ts`:
- Around line 801-804: The split in parsePackageManager misparses scoped
package-manager specs like "`@scope/pm`@1.2.3" because packageManager.split('@')
splits at every '@'; change the logic in parsePackageManager to locate the last
'@' (or treat leading '@' specially) and split on that last occurrence so the
name retains the scope (e.g., "`@scope/pm`") and pmReference becomes the trailing
reference; update any comments referring to "pmReference is semantic versioning"
accordingly and ensure the returned shape ({ name, version, hash }) continues to
derive version/hash from the pmReference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eaa74afa-8c96-41ea-a649-d0c787352e16

📥 Commits

Reviewing files that changed from the base of the PR and between d188316 and 3301ab5.

📒 Files selected for processing (4)
  • .changeset/devengines-package-manager-same-hash.md
  • config/reader/src/index.ts
  • config/reader/test/index.ts
  • pnpm/test/packageManagerCheck.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Compile & Lint
  • GitHub Check: Analyze (javascript)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Use Standard Style with trailing commas, prefer functions over classes, declare functions after they are used (relying on hoisting), limit functions to no more than two or three arguments, and use a single options object for functions needing more parameters
Follow import order: standard libraries first, then external dependencies (sorted alphabetically), then relative imports
Do not write comments that restate what the code already says; rename variables, split helpers, or move checks to more obvious places instead
Do not repeat documentation at call sites that already lives on the callee; update the JSDoc once and let every call site benefit
Use JSDoc for the function's contract (preconditions, postconditions, edge cases, why the function exists), not for re-narrating the function body
Do not record past implementation shape, refactor history, or removed code in comments; use git log and git blame for that information instead
Write comments only when the reason for code is non-obvious, a hidden invariant exists, a workaround for a known bug is needed, or an exception to surrounding pattern is deliberate

Files:

  • config/reader/test/index.ts
  • config/reader/src/index.ts
  • pnpm/test/packageManagerCheck.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not use instanceof Error for checking if a caught error is an Error object in Jest tests; use util.types.isNativeError() instead to work across realms

Files:

  • pnpm/test/packageManagerCheck.test.ts
🧠 Learnings (5)
📚 Learning: 2026-05-26T21:01:06.666Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11966
File: .changeset/require-tarball-integrity.md:6-6
Timestamp: 2026-05-26T21:01:06.666Z
Learning: In pnpm lockfile-related release notes/docs (especially changeset markdown), preserve URL hostnames exactly as they appear in pnpm-lock.yaml tarball resolution entries—keep hosts like `codeload.github.com`, `bitbucket.org`, and `gitlab.com` in lowercase. Do not “correct” them to title-case/preserve brand capitalization (e.g., LanguageTool rules like `GITHUB` capitalization) because these are literal URL fragments, not platform brand names.

Applied to files:

  • .changeset/devengines-package-manager-same-hash.md
📚 Learning: 2026-05-14T09:04:00.133Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11622
File: resolving/npm-resolver/test/publishedBy.test.ts:350-354
Timestamp: 2026-05-14T09:04:00.133Z
Learning: In the pnpm/pnpm repository, ESLint is the authoritative style linter. Do not raise review findings for missing trailing commas in multiline function calls (e.g., `fs.writeFileSync(...)`) when this repo’s ESLint configuration does not report them and lint passes. Prefer deferring to the ESLint results for this specific trailing-comma rule rather than enforcing it manually in code review.

Applied to files:

  • config/reader/test/index.ts
  • config/reader/src/index.ts
  • pnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-06-05T13:47:05.929Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/test/install/frozenStore.ts:2-17
Timestamp: 2026-06-05T13:47:05.929Z
Learning: In the pnpm/pnpm repository, the shared Jest preset keeps `injectGlobals` at its default (`true`), so `test` and `expect` are available as Jest globals. Therefore, reviewers should not flag (or treat as TypeScript/compilation errors) missing `import { test, expect } from 'jest/globals'` when a test file uses `test`/`expect` without importing them. Importing from `jest/globals` may still be used for consistency with sibling files, but it is not required for execution in this repo unless a Jest preset is explicitly configured with `injectGlobals: false`.

Applied to files:

  • config/reader/test/index.ts
  • pnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-06-05T13:47:26.046Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/src/install/index.ts:2337-2343
Timestamp: 2026-06-05T13:47:26.046Z
Learning: In the pnpm/pnpm codebase, `PnpmError` automatically prefixes `err.code` with `ERR_PNPM_` when you pass a code that does not already start with `ERR_PNPM_` (it normalizes `this.code` via `code.startsWith('ERR_PNPM_') ? code : `ERR_PNPM_${code}``). Therefore, during code review you should NOT flag `new PnpmError(...)` call sites for passing a bare error code (e.g., `new PnpmError('FROZEN_STORE_INCOMPATIBLE_WITH_PNPR', ...)`); the resulting `err.code` will still be `ERR_PNPM_FROZEN_STORE_INCOMPATIBLE_WITH_PNPR`.

Applied to files:

  • config/reader/test/index.ts
  • config/reader/src/index.ts
  • pnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-05-24T08:18:00.622Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11895
File: pnpm/test/deploy.ts:91-95
Timestamp: 2026-05-24T08:18:00.622Z
Learning: In pnpm/pnpm integration tests that intentionally hit the real npm registry (registry.npmjs.org)—for example when the test passes `--config.registry=https://registry.npmjs.org/` to `execPnpm` and simply increases the timeout—do not request adding a runtime environment-variable gate (e.g., `PNPM_RUN_PUBLIC_REGISTRY_TESTS`). This is the established pattern for those tests (see files like `pnpm/test/install/pacquet.ts` and `pnpm/test/deploy.ts`).

Applied to files:

  • pnpm/test/packageManagerCheck.test.ts
🔇 Additional comments (3)
.changeset/devengines-package-manager-same-hash.md (1)

1-9: LGTM!

config/reader/test/index.ts (1)

210-271: LGTM!

pnpm/test/packageManagerCheck.test.ts (1)

509-565: LGTM!

Also applies to: 581-583, 599-601

Comment thread config/reader/src/index.ts Outdated
@spencerbeggs spencerbeggs requested a review from Copilot June 9, 2026 16:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread config/reader/src/index.ts Outdated
Comment thread config/reader/src/index.ts
Comment thread config/reader/src/index.ts Outdated
Comment thread config/reader/src/index.ts Outdated
Comment thread config/reader/test/index.ts
Comment thread config/reader/test/index.ts
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 9, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit f782957

@spencerbeggs spencerbeggs requested a review from Copilot June 9, 2026 16:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread config/reader/src/index.ts
@spencerbeggs spencerbeggs force-pushed the fix/silence-conflict-warnings-with-same-hash branch from f782957 to 7010003 Compare June 9, 2026 17:02
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 9, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 7010003

@spencerbeggs spencerbeggs requested a review from Copilot June 9, 2026 17:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@spencerbeggs spencerbeggs force-pushed the fix/silence-conflict-warnings-with-same-hash branch from 7010003 to f363f62 Compare June 10, 2026 20:55
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 10, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit f363f62

The conflict warning between the legacy "packageManager" field and
"devEngines.packageManager" fired even when both pinned the same package
manager at the same version, because the integrity hash was stripped from
the legacy field but not from devEngines, so identical specifications
compared unequal.

Parse the hash out of both sides and compare the semver parts plus the
hashes: keeping the two fields in sync, hash included, is now quiet, while
two contradictory hashes for the same version are still reported. Each
conflict now also names its specific cause — a different package manager, a
different version, or contradictory integrity hashes — instead of a single
generic message.

Closes pnpm#12028

Signed-off-by: C. Spencer Beggs <spencer@beggs.codes>
@zkochan zkochan force-pushed the fix/silence-conflict-warnings-with-same-hash branch from f363f62 to d784ac7 Compare June 16, 2026 11:10
Copilot AI review requested due to automatic review settings June 16, 2026 11:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 16, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit d784ac7

Comment thread config/reader/src/index.ts
…flict warnings

The legacy "packageManager" and "devEngines.packageManager" conflict
warnings interpolate package.json-controlled name and version values into
text printed to the terminal. Strip ANSI escape sequences and other control
characters first so a malicious manifest cannot forge or rewrite terminal/CI
log output.

Signed-off-by: Zoltan Kochan <z@kochan.io>
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 16, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 125c2e5

@zkochan zkochan enabled auto-merge (squash) June 16, 2026 12:07
@zkochan zkochan disabled auto-merge June 16, 2026 13:48
@zkochan zkochan merged commit 302a2f7 into pnpm:main Jun 16, 2026
18 checks passed
@welcome

welcome Bot commented Jun 16, 2026

Copy link
Copy Markdown

Congrats on merging your first pull request! 🎉🎉🎉

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.

packageManager/devEngines.packageManager conflict warning still showing for equivalent versions using hashes

3 participants