Every recommendation OSS IQ can make¶
Part of Recommendations and Risk.
Five distinct kinds of output tell you to do something. They are computed by different modules against different evidence, and they are not rankings of each other.
The target — recommended_version + recommended_from_rung¶
The version to move to, and which rung of the version ladder it came from.
Rung |
Meaning |
Writable by |
|---|---|---|
|
the SAT solver’s own pick, inside the declared constraint |
yes |
|
newest version satisfying the declared constraint |
yes |
|
newest within the installed major line — outside the declared range |
only if the tier authorizes widening |
|
newest overall — outside the declared range |
only if the tier authorizes widening |
The rung, not the version, decides whether apply may write. in_major and latest require
rewriting the manifest’s declared range first, so build_update_plan withholds them into
Requires constraint widening unless the run’s tier reaches that far or a CVE or end-of-life motive carried the pick past it (widening_authorized). status and the agent
payload still show them — with requires_constraint_widening: true — because knowing a newer
version exists is useful even when taking it needs a human decision.
next_action — the one-line headline¶
One label per package, first match wins, most urgent first:
Label |
Fires when |
What it does not mean |
|---|---|---|
|
a CVE with EPSS ≥ 0.10 |
not “a fix exists” — only that exploitation is probable |
|
already at latest and upstream is not maintained |
— |
|
upstream is |
not abandoned; not urgent |
|
major-version drift |
not “this will break” |
|
minor/patch drift with a writable in-range target |
— |
|
minor/patch drift and the declared range admits nothing newer |
not “the package is broken” — the range is the thing to change |
|
minor/patch drift, a bump is reachable, but the tier admitted no motive |
not the constraint’s fault — a higher |
(none) |
nothing is due |
— |
The two are decided in different places and must not be confused. Constrained. Check newer version is a fact about the manifest: the declared range admits nothing newer than what is
installed, so widening it is the next step. Withheld by strategy is a fact about this run:
security and deprecation move a package only on a qualifying motive, and without one the
package is left alone however much newer the registry has gone. The ↳ sub-row under each names
its own cause, and the withheld one names the lowest tier that would move it — so a second run at
a higher tier is a confirmation, never a cross-check you are obliged to perform.
dependency_health (triage) — the operational verdict¶
From the EPSS × maintenance matrix (see Repository stability):
retain, patch, refactor, evict. Advisory only — it appears on every surface but changes
no recommendation and gates no build. The agent payload and MCP tools name it dependency_health,
and the JSON export dependency_health_action. It answers “is this dependency healthy long-term?”;
next_action answers “what do I do now?”.
The add decision — install / install with caution / do not install¶
Produced by ossiq add and the ossiq_evaluate_dependency MCP tool, for a package not yet in the
tree. do not install on critical health warnings; --force overrides.
The non-recommendations¶
These carry as much decision-making weight as the targets, and are easier to skim past:
Output |
Means |
Where |
|---|---|---|
|
no motive admitted at this tier; names the lowest tier that would move it |
|
Held for cooldown |
target is younger than |
|
Requires constraint widening |
target sits outside the declared range and neither the tier nor an escalating motive authorizes rewriting it |
|
|
a newer release was found and held back — by a transitive conflict, a peer dependency range, a known module-system break, or an engine mismatch — one per rung, with the reason. On npm a transitive conflict means an |
|
Held by overrides you wrote |
an |
|
Held by peer dependencies |
a newer release exists, but an installed package’s |
|
Repairs unresolved peers |
a peer is installed only where its requirer cannot load it, and |
|
|
the peers a package declares that nothing within its reach satisfies |
|
|
no version satisfies all constraints ( |
|
|
reach was pushed past the tier’s base, or every reachable version still carries a CVE |
export |
|
a CVE or end-of-life motive carried the pick past the tier’s base reach, so |
export |
New transitive dependency |
a package entering the tree for the first time, younger than the cooldown. Resolved by the native package manager, so the cooldown hold cannot apply to it |
|
A blank Recommended cell with no accompanying ↳ row means OSS IQ found nothing newer. A blank
cell with a ↳ row means it found something and refused it, and the row says why. The
commonest case: a CommonJS project already at the top of its CommonJS line, whose only newer
releases are ESM-only (↳ 6.0.0 rejected: ESM-only from 6.0.0). See
The module-system line.
What the recommendation catalogue risks¶
Mistaking advice for a gate.
dependency_health_actionandnext_actionchange no exit code.ossiq statusexits 0 on a project full ofevictverdicts. Any CI gate is yours to write, over the JSON export. The single exception is not a gate but a refusal: asecurity/deprecationrun whose vulnerability data never arrived exits non-zero rather than report an empty result it cannot back up — see Partial data.Reading one surface only. The target lives in Recommended; the reason it is what it is lives in the
↳rows (--full), ininfo’s Policy Compliance block, or in the agent payload’sreasonsarray. The default console view is deliberately narrow.Assuming the headline covers the package.
next_actionis one label chosen by priority. A package can be simultaneously CVE-affected, deprecated and three majors behind, and print onlyCheck for the Fix.