Compatibility
How bellpull's drop-ins are graded — cross-spawn 68 / 68 and node-which 5 / 5 by their own suites — and why execa's suite grades bellpull 0 / 1048 and is declared a ceiling, not a drop-in.
bellpull/cross-spawn and bellpull/node-which are graded, not described as compatible. Each
is run against its incumbent's own test suite, by
compat-oracle,
in CI. execa's suite is run too, to measure the answer rather than state it.
✓ yes · ◐ partial, with what is missing · ✗ no · — does not apply. Every mark links to its evidence: our test or grade, or the incumbent’s source at the version compat-oracle grades.
| Capability | bellpull | execa | cross-spawn | which |
|---|---|---|---|---|
| Compatibility | ||||
Passes cross-spawn's own test suitebellpull/cross-spawn is graded by cross-spawn 7.0.6's own tests, each case run four ways, so changing the import keeps cross-spawn's behaviour. | bellpull: yes68 / 68 of its own tests | execa: does not applya different API | cross-spawn: yesits own suite, the control run | which: does not applya different API |
Passes which's own test suitebellpull/node-which is graded by node-which 7.0.0's own tests, each run under posix and win32 and through both which() and which.sync(). | bellpull: yes5 / 5 of its own tests | execa: does not applya different API | cross-spawn: does not applya different API | which: yesits own suite, the control run |
execa's own test suite: not a drop-inexeca 10.0.1's suite is run against bellpull so the answer is measured: every file fails to import execa, which bellpull does not export, and the row is a declared ceiling rather than a migration path. | bellpull: no0 / 1,048 of its own tests | execa: yesits own suite, the control run: 1,048 of 1,048 | cross-spawn: does not applya different API | which: does not applya different API |
Compatibility
Passes cross-spawn's own test suite
bellpull/cross-spawnis graded by cross-spawn 7.0.6's own tests, each case run four ways, so changing the import keeps cross-spawn's behaviour.Passes which's own test suite
bellpull/node-whichis graded by node-which 7.0.0's own tests, each run underposixandwin32and through bothwhich()andwhich.sync().cross-spawn- cross-spawn: does not applya different API
execa's own test suite: not a drop-in
execa 10.0.1's suite is run against
bellpullso the answer is measured: every file fails to importexeca, which bellpull does not export, and the row is a declared ceiling rather than a migration path.cross-spawn- cross-spawn: does not applya different API
The family's compatibility page is generated from the oracle's last run and is the authority for the current figures.
How a suite is graded
- The incumbent's repository is cloned at the release tag of the graded version —
cross-spawn 7.0.6, which 7.0.0, execa 10.0.1 — and its test directory copied into
packages/compat-oracle/vendor/, with aPROVENANCEfile naming the tag, the commit and the command that reproduces it. - The only edit is the import that reaches the library, rewritten to a shim generated per run.
- A control run points the shim at the real incumbent first; its total is what every rate is measured against.
- The target run points the same shim at bellpull.
What each grade covers
- cross-spawn — 68 of 68. Every case runs four ways —
spawn,spawnwith a forced shell,sync, andsyncwith a forced shell. On POSIX cross-spawn is a pass-through, so the suite never reaches the Windows escaping or thecmd.exebranch: replacing the escaper witharg => `"${arg}"`— the injection bug in its purest form — leaves the row at 68 / 68. That half is covered by bellpull's own tests (Windows). - which — 5 of 5. node-which 7's
test/index.js, againstbellpull/node-which. Five is the suite's count of top-level tests, each run underposixandwin32and through bothwhich()andwhich.sync().test/bin.jsgrades node-which's command-line tool, which bellpull does not ship, and is not graded. - execa — 0 of 1,048, a ceiling. The 1,048 are execa's
arguments/,methods/andreturn/directories. Every file importsexeca, which bellpull does not export, so each dies before a case runs; the other nine directories read the same zero and are left out of the recurring grade because the whole suite takes about eleven minutes. Declaring the row a ceiling keepsburgee migratefrom ever rewriting an execa import to bellpull.
Known differences
bellpull/node-whichis synchronous underneath.which()runs the same search aswhich.sync()and returns it as a promise, rather than walking the filesystem asynchronously.bellpull/whichis not the drop-in. It is bellpull's own resolver: it returns{ path, from, ext }rather than a string, and skips empty and relativePATHentries.bellpull/cross-spawnon Windows handscmd.exethe command as written, exactly as cross-spawn does, socmd.exeresolves a bare name again in the child's environment. Building the line from the resolved path would be a divergence from cross-spawn that its suite could not see; it is recorded inrun.tsrather than quietly changed.
Moving one import
- import spawn from 'cross-spawn';
+ import spawn from 'bellpull/cross-spawn';- import which from 'which';
+ import which from 'bellpull/node-which';npx burgee migrate --dry-run lists every import it would rewrite — only drop-ins graded level
with their incumbent — and npx burgee migrate makes the change.
Incremental migration moves a call site from the
drop-in to run().
Why bellpull
bellpull against execa, cross-spawn and which, one capability per row — including the rows where execa is ahead — every cell linked to the test, grade or source that proves it.
Coming from execa
An execa alternative with zero dependencies: bellpull's run() treats a non-zero exit as a value, not an exception, says which binary ran, and renders one result as text, --json or an agent event. Not an execa drop-in: execa's own suite grades it 0 / 1048, and that zero is the design.