Engine constraints¶
Part of Recommendations and Risk.
An “engine” is the runtime a release declares it needs: engines.node on npm, requires-python on
PyPI. A release that cannot run on your runtime is not a candidate, however new it is.
Which runtime gets checked¶
Two things can speak for an engine, and an engine requirement has to hold for both:
the runtime: the version the caller states (MCP
runtime, which is required there, or--engine node=<version>on the CLI), or else, on the CLI only, the probe: the project’s virtualenv Python, ornode --versionandnpm --versionfromPATH;the declared floor — the lowest version the project’s own manifest claims to support (
requires-python,engines.node), reduced to a concrete version per engine key.
Each engine is held to whichever of the two is lower, because that is the one a requirement
fails against first. A project declaring requires-python = ">=3.11" on a machine running 3.13 is
held to 3.11: a release needing 3.12 breaks that project’s own 3.11 users, and uv — which
resolves every Python version in the declared range — will refuse it at apply time even though
it runs fine here.
engine_context_source then says which side is binding:
Source |
Meaning |
|---|---|
|
the caller-stated runtime binds for every engine — no declared floor is lower |
|
the probe binds for every engine — no declared floor is lower |
|
the manifest floor binds for at least one engine |
|
neither was available; no engine checking happens at all |
Probes are gated by registry: a pure-PyPI scan never spawns node --version. A stated runtime
replaces the probe entirely. The MCP server never probes, because its PATH belongs to whatever
process launched it, not to the shell the project’s tests run in. That difference alone made two
identical requests disagree.
A stated or probed runtime is also checked against the version pins the project keeps for its
own tooling (.nvmrc, .node-version, .tool-versions, mise.toml, volta.node,
.python-version, .venv/pyvenv.cfg). A disagreement is reported as runtime_mismatch, never
silently resolved: a pin says what developers run, not what the project supports.
Both sides carry npm as well as node, so a release declaring engines.npm is checked too —
the two share one semver grammar and one matcher. pnpm and yarn are deliberately not
evaluated: OSS IQ has no adapter for either, so nothing probes them, and a floor checked on the
declared path but not the detected one would be worse than no check at all. They pass through as
satisfied like any other engine key OSS IQ cannot evaluate.
One definition, three consumers¶
engine_mismatch_reason is the single engine check. The solver’s ranking clauses, the record’s
engine_compatible flag, and the candidate gate in the strategy pipeline all derive from it, so a
candidate the gate rejects can never disagree with the verdict written onto the record. The reason
string it returns is the one you read:
↳ requires node >=22.0.0, checked against 18.0.0 (detected)
engine_compatible is tri-state¶
False = a conflict was found. True = checked and clear. None = the question was never
answerable — the release declares no requirement, or there was no runtime to check against.
None never means compatible.
The escape hatch¶
If the engine gate would reject every installable release, OSS IQ drops the gate for that pass
rather than blanking the recommendation — the same rule it applies when every reachable version
carries a CVE. You get the newest version, with engine_compatible: false on the record and a red
↳ row naming the mismatch. A recommendation can be incompatible with your runtime and still be
the best available answer; OSS IQ’s obligation is to say so, not to hide it.
What engine handling risks¶
Risk |
Detail |
|---|---|
The runtime may not be the deployed one |
A stated runtime is whatever the caller read. A probed one is whatever is on the |
The declared floor is a floor, not your runtime |
Whenever the floor is the lower of the two, checks run against the lowest version the manifest supports. A package requiring |
The check fails open |
An engine key nothing can evaluate ( |
An engine absent from the context is never checked |
The check iterates the runtime versions it has, not the requirements a release declares. A |
|
An absent requirement and a verified pass are different states and look similar in JSON. |