Skip to main content

JavaScript Dependency Governance

Use when governing npm dependency support migrations.

Purpose​

Use this skill when npm emits deprecation warnings or installed/transitive packages are unsupported. The goal is not quiet output; it is a supported installed and shipped graph with preserved application and packaging behavior.

Apply the general migration lifecycle from deprecation-and-migration, then use this npm-specific workflow.

Interpret the Requirement​

Separate these states before editing:

  • Deprecated but supported: potentially acceptable when the user permits it.
  • Unsupported or unmaintained: remove from the installed/shipped graph when support is required.
  • Lockfile metadata only: may describe a peer or optional package that is not physically installed.
  • Installed development tooling: matters even when absent from production bundles.
  • Packaged runtime dependency: highest priority because users execute it.

Do not treat every npm WARN deprecated line as equal. Read the exact warning and upstream support evidence. Conversely, quiet stdout alone does not prove a supported graph.

Workflow​

1. Reproduce cleanly​

Use a clean worktree at the verified remote base. Capture a true clean install:

set -o pipefail
npm ci 2>&1 | tee /tmp/npm-ci-baseline.log

Count warning lines programmatically. Record exact package names, versions, and warning text.

2. Map ancestry and installation class​

For every warning or unsupported package, run:

npm explain <package>
npm ls <package> --all --json

Classify each path as direct, transitive, peer, optional, platform-specific, runtime, development-only, or packaging-only. Inspect package-lock.json flags and nested paths. Never choose a fix from the package name alone.

3. Bound behavior before replacement​

Search imports, target configuration, scripts, tests, packaging metadata, and public callers. List invariants that must survive:

  • public API and output format;
  • streaming/file-descriptor and error-propagation semantics;
  • installer and artifact targets;
  • resource inclusion;
  • native ABI transitions;
  • security and race guarantees.

Prefer a maintained API-compatible replacement when it reduces risk. Rewrite only when compatible options cannot satisfy support or behavior requirements.

4. Treat omitted peers as target exclusions​

Omitting peers is valid only when all are proven:

  1. the peer belongs solely to an unconfigured feature/target;
  2. configuration and policy reject that target;
  3. the parent lazy-loads the peer only for that target;
  4. every required peer is installed through a supported path;
  5. all supported package targets are tested.

A repository .npmrc with omit=peer is too broad without these proofs. Do not use it merely to hide warnings.

5. Treat overrides as compatibility contracts​

An override is acceptable only when it selects a supported version and compatibility is proven against the parent package's actual imported APIs. Pin it exactly, document the contract, test it, and build every affected target.

Reject overrides used only to quiet installation, overrides crossing APIs without evidence, and prerelease parent versions unless the user explicitly accepts prerelease risk.

6. Enforce metadata and physical state​

The dependency policy must check:

  • direct dependency ranges;
  • required exact compatibility overrides;
  • forbidden and required package targets;
  • deprecated/explicitly unsupported installed packages;
  • exact physical package path/version correspondence to the lockfile;
  • absent deprecated peer/optional metadata only when intentionally excluded;
  • scoped and nested packages;
  • symlink traversal cannot escape node_modules.

Do not derive the physical inventory only from lockfile entries. That misses extraneous packages placed in node_modules outside the lock.

7. Test policy RED to GREEN​

Use isolated fixtures and prove:

  • unsupported package physically present but absent from lock fails;
  • installed version differing from lock fails;
  • nested and scoped unsupported packages fail;
  • intentionally omitted deprecated peer metadata passes only when absent;
  • enabling the excluded target fails;
  • removing a required override fails.

Run the bypass test against the old policy and observe RED before implementing GREEN.

8. Verify independently​

Use separate commands or &&/set -e; semicolon-separated commands expose only the last exit status.

Required layers:

  1. clean npm ci and warning count;
  2. dependency policy;
  3. targeted npm ls proof;
  4. focused behavior/security tests;
  5. typecheck and lint;
  6. full suite;
  7. application build;
  8. audit policy;
  9. every supported package target;
  10. packaged-content inspection for forbidden modules and required resources.

For Electron apps, inspect app.asar plus external resources. Linux packaging does not prove NSIS or DMG behavior. If packaging rebuilds native modules for Electron, restore the Node ABI before rerunning tests.

9. Preserve exact-head evidence​

Refetch the base before push. If it moved, incorporate it and rerun gates. Reviews bind to one exact commit. Remediation creates a new head requiring fresh review. Post request-changes and approval receipts with their exact heads.

Failure Modes​

  • Suppressing warnings instead of changing support status.
  • Accepting a prerelease parent package as stable by default.
  • Assuming clean npm ci means the policy cannot be bypassed.
  • Scanning only lock metadata and missing extraneous installed packages.
  • Omitting peers without target-specific proof.
  • Proving only Linux packaging for a Windows/macOS contract.
  • Rewriting a broad API when a maintained compatible implementation exists.
  • Treating a semicolon chain's final zero status as proof of all gates.
  • Keeping fixed test counts in build docs; prefer invariant expectations.

Completion Checklist​

  • Deprecated versus unsupported criteria match the user's requirement.
  • Every warning has mapped ancestry and installation class.
  • Replacement, override, and omission choices have upstream/behavior evidence.
  • Clean install and installed graph meet the requirement.
  • Physical inventory is checked independently of the lockfile.
  • Policy bypass regressions pass.
  • Behavior and security invariants pass.
  • Every supported package target has native evidence or is marked outstanding.
  • Packaged contents exclude forbidden modules and include resources.
  • Exact-head reviews rerun after every mutation.

Reference​

See references/electron-packaging-peer-chain.md for a versioned case study covering an unused installer peer chain, supported overrides, physical-inventory policy tests, and package inspection.


Supporting files: this skill's supporting files are held in the docsite at docs/15-skills/_support/engineering/javascript-dependency-governance/ — fetch them fresh from jknash/docsite main alongside this page. Source: jknash/hermes-shared-skills · branch hermes-jkdev001 @ 1d0d545c3970 · skills/engineering/javascript-dependency-governance/ · view source · Imported 2026-10-04. Supporting files (references, scripts) remain in the source repository.

Published by Muse · 2026-10-04.