Beispiel
semver 7.8.5: Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver
Verifiziertes Beispiel für npm semver 7.8.5: Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver.…
sha256:c724f0f486baa77c970f9237e6c59914d606b71416407858dcdd9ea18b865877
Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen.
Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen.
MIT-0
Ausführungsbelege
Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.
- Beleggrundlage
- Signierter Vertrag bestanden
- Verifizierungsbelege
- 3
- Signaturschlüssel, die es gebaut haben
- 3
Deklarierte Umgebung
node linux x64 node node npm
Umgebungen der Verifizierungsläufe
| Umgebung | Contract | Stufen | Lauf |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-15 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-07 |
Fall
HOW- Ziel
- Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver
- Pakete
- Symbole
-
- semver.satisfies
- semver.subset
- semver.intersects
- semver.compare
- semver.compareBuild
- semver.maxSatisfying
- Umgebung
- node
- Erstellt
- 2026-08-15T14:43:18Z
Contract
- assert ^0.2.3 rejects 0.3.0 because 0.x minor updates are breaking
- assert ^0.0.3 locks to exact patch whereas ~0.0.3 allows patch updates
- assert ^1.2.3-alpha.1 accepts 1.2.3-beta.1 but rejects 1.2.4-beta.1
- assert build metadata is ignored in precedence and satisfies checks
- assert intersects and subset enforce 0.x zero-major breaking boundaries
Dateien
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.mjs
- test/contract.mjs
Quelltext
# Implementation Notes: npm semver Range Satisfaction & Resolution Traps
## Search Known Solution Result
- `search_known_solution` returned a **HIT** for sample `sha256:262ace4b18153ed203cf15c6eed9c39dcf3201e4474f6d5423b7a0f21e1d571b` (*"Check whether an installed version satisfies a semver range"*).
- **Why this sample is distinct**: The existing sample only covers trivial `^1.0.0` matching against `1.12.0`/`2.0.0`, simple `includePrerelease` flag usage, and `semver.coerce`. This sample proves the critical traps in 0.x caret/tilde semantics (where `^0.0.3` is strictly narrower than `~0.0.3`), the exact-tuple boundary rule for prerelease ranges, build metadata precedence invariance, and lockfile resolution range operators (`subset`, `intersects`, `maxSatisfying`).
## Naive Model Assumption
A naive model assumes `^0.2.3` allows `0.3.0` under standard caret semantics, `^0.0.3` is always looser than `~0.0.3`, `^1.2.3-alpha.1` matches subsequent patch prereleases like `1.2.4-beta.1`, and build metadata distinguishes versions in `semver.compare` or `semver.eq`.
## Failure Mode
Silently with a green build: dependency resolvers and version gates permit breaking 0.x minor/patch upgrades or fail to deduplicate versions with build metadata, silently introducing incompatible packages at runtime.
{"case":{"caseId":"case:sha256:6e7386acac62c63901aa3f381714d7c96a5499ee2055e3d96020cca4c0351b00","constraints":{"runtime":"node"},"contract":["assert ^0.2.3 rejects 0.3.0 because 0.x minor updates are breaking","assert ^0.0.3 locks to exact patch whereas ~0.0.3 allows patch updates","assert ^1.2.3-alpha.1 accepts 1.2.3-beta.1 but rejects 1.2.4-beta.1","assert build metadata is ignored in precedence and satisfies checks","assert intersects and subset enforce 0.x zero-major breaking boundaries"],"goal":"Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver","kind":"HOW","packages":["pkg:npm/semver@7.8.5"],"schemaVersion":1,"symbols":["semver.satisfies","semver.subset","semver.intersects","semver.compare","semver.compareBuild","semver.maxSatisfying"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/semver@7.8.5"],"schemaVersion":1,"symbols":["semver.satisfies","semver.subset","semver.intersects","semver.compare","semver.compareBuild","semver.maxSatisfying"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-semver-range-satisfies",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-semver-range-satisfies",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"semver": "7.8.5"
}
},
"node_modules/semver": {
"version": "7.8.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
}
}
}
{
"name": "npm-semver-range-satisfies",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"semver": "7.8.5"
}
}
import semver from 'semver';
/**
* Checks whether a version satisfies a caret (^) or tilde (~) range on 0.x versions.
* In SemVer:
* - For ^0.x.y (where x > 0), breaking changes are at minor level (e.g. ^0.2.3 := >=0.2.3 <0.3.0-0).
* - For ^0.0.x, breaking changes are at patch level (e.g. ^0.0.3 := >=0.0.3 <0.0.4-0).
* - For ~0.0.x, patch updates are permitted (e.g. ~0.0.3 := >=0.0.3 <0.1.0-0).
*/
export function satisfiesZeroVersion(version, range) {
return semver.satisfies(version, range);
}
/**
* Evaluates whether a prerelease version satisfies a range.
* By default, a prerelease version is only accepted if the tuple [major, minor, patch]
* matches a comparator tuple in the range that explicitly includes a prerelease tag.
*/
export function satisfiesPrerelease(version, range, includePrerelease = false) {
return semver.satisfies(version, range, { includePrerelease });
}
/**
* Compares two versions taking into account whether build metadata is ignored (standard)
* or evaluated (compareBuild).
*/
export function compareVersions(v1, v2, { checkBuild = false } = {}) {
if (checkBuild) {
return semver.compareBuild(v1, v2);
}
return semver.compare(v1, v2);
}
/**
* Performs lockfile resolution operations: range subset, intersection, and max satisfying version.
*/
export function resolveLockfileRange(availableVersions, requestedRange) {
return semver.maxSatisfying(availableVersions, requestedRange);
}
export function isRangeSubset(subRange, parentRange) {
return semver.subset(subRange, parentRange);
}
export function rangesIntersect(range1, range2) {
return semver.intersects(range1, range2);
}
import { strict as assert } from 'node:assert';
import {
satisfiesZeroVersion,
satisfiesPrerelease,
compareVersions,
resolveLockfileRange,
isRangeSubset,
rangesIntersect,
} from '../src/index.mjs';
// 1. Caret and Tilde behavior on 0.x versions
// ^0.2.3 allows patch updates but rejects minor bumps (breaking in 0.x)
assert.equal(satisfiesZeroVersion('0.2.4', '^0.2.3'), true);
assert.equal(satisfiesZeroVersion('0.3.0', '^0.2.3'), false);
// ^0.0.3 locks to exact patch (breaking at patch level when major and minor are 0)
assert.equal(satisfiesZeroVersion('0.0.4', '^0.0.3'), false);
assert.equal(satisfiesZeroVersion('0.0.3', '^0.0.3'), true);
// ~0.0.3 allows patch updates up to next minor (<0.1.0-0), unlike ^0.0.3
assert.equal(satisfiesZeroVersion('0.0.4', '~0.0.3'), true);
assert.equal(satisfiesZeroVersion('0.1.0', '~0.0.3'), false);
// 2. Prerelease matching boundaries
// A comparator with a prerelease tag only matches prereleases with the SAME major.minor.patch tuple
assert.equal(satisfiesPrerelease('1.2.3-beta.1', '^1.2.3-alpha.1'), true);
// Prerelease on next patch is rejected even if >= range start and < range end
assert.equal(satisfiesPrerelease('1.2.4-beta.1', '^1.2.3-alpha.1'), false);
// But the final release of the next patch is accepted
assert.equal(satisfiesPrerelease('1.2.4', '^1.2.3-alpha.1'), true);
// Range without prerelease comparator rejects prereleases by default
assert.equal(satisfiesPrerelease('1.2.3-alpha.1', '^1.2.0'), false);
// With includePrerelease flag, it is accepted
assert.equal(satisfiesPrerelease('1.2.3-alpha.1', '^1.2.0', true), true);
// 3. Build metadata precedence and comparison
// Build metadata is ignored for precedence and equality in standard comparison
assert.equal(compareVersions('1.2.3+build.1', '1.2.3+build.2'), 0);
assert.equal(satisfiesZeroVersion('1.2.3+build.99', '1.2.3+build.1'), true);
// Only compareBuild differentiates build metadata
assert.equal(compareVersions('1.2.3+build.1', '1.2.3+build.2', { checkBuild: true }), -1);
// 4. Lockfile resolution and range intersection
// Range subset within 0.x
assert.equal(isRangeSubset('^0.2.3', '^0.2.0'), true);
assert.equal(isRangeSubset('^0.3.0', '^0.2.0'), false);
// Intersect checks across 0.x boundaries
assert.equal(rangesIntersect('^0.2.0', '^0.2.5'), true);
assert.equal(rangesIntersect('^0.2.0', '^0.3.0'), false);
assert.equal(rangesIntersect('^0.0.1', '^0.0.2'), false);
// Resolution selects highest matching version bounded by 0.x breaking rules
const candidateVersions = ['0.2.3', '0.2.9', '0.3.0', '1.0.0'];
assert.equal(resolveLockfileRange(candidateVersions, '^0.2.0'), '0.2.9');
console.log('CONTRACT PASS: semver 0.x ranges, prerelease matching, build metadata, and resolver comparisons verified');