npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ushman-equiv

v0.4.0

Published

Pure-Node equivalence checks for ushman refactors. Runs import-graph, module-load, symbol-diff, and replay tiers inside Node-only sandboxes.

Readme

ushman-equiv

Pure-Node behavioral and structural equivalence checks for ushman refactors.

Runs four Node-only tiers against a candidate workspace: import-graph resolution, module-load smoke, symbol-preservation diff, and replay against captured fixtures. Designed for the same air-gapped handoff zips and local-link workflows as @ushman/verify.

When runEquiv() executes multiple tiers together, it shares entrypoint discovery, source walking, and AST parsing across tiers so each source file is parsed once per run.

flowchart LR
    A["runEquiv(opts)"] --> B["EquivExecutionContext"]
    B --> C["Analysis Context"]
    B --> D["Candidate Boot"]
    C --> E["Tier I: import graph"]
    C --> F["Tier S: symbol diff"]
    C --> G["Tier L: module load"]
    C --> H["Tier R: replay"]
    D --> G
    D --> H

Status

Extracted as a sister package for the cleanup lane. Runtime: pure Node ≥ 24. No Bun APIs in published runtime code. Tests run with Bun. Distribution: local-link only for now. Do not publish to npm in v0.

Install

cd ~/workspace/ushman-lab-types
bun link

cd ~/workspace/ushman-equiv
bun link

cd ~/workspace/ushman
bun link ushman-equiv

Quick start

import { runEquiv } from 'ushman-equiv';

const report = await runEquiv({ workspaceRoot: '.' });
console.log(report.verdict); // 'green' | 'yellow' | 'red'
ushman-equiv .                        # all tiers
ushman-equiv ./candidate --tier=R
ushman-equiv emit-baseline --workspace=.

Tiers

| Tier | What it checks | |------|----------------| | I | Static import-graph resolution for relative imports and bare specifiers against the workspace importmap | | L | Child-process module-load smoke with browser-global shims and vendor stubs | | S | Baseline vs candidate top-level symbol preservation | | R | Replay of captured fixture calls against refactored exports |

Public API

See src/index.ts for the full surface. Top-level:

runEquiv(opts: EquivOptions): Promise<EquivReport>;
renderEquivReport(report: EquivReport): string;
writeEquivResult(opts: { report: EquivReport; workspaceRoot: string }): Promise<void>;
emitSymbolBaseline(opts: { workspaceRoot: string; outputPath?: string }): Promise<{ symbolCount: number; outputPath: string }>;
canonicalize(value: unknown, opts?: { precision?: number; exemptFields?: readonly string[]; maxBytes?: number }): unknown;

canonicalize() treats exemptFields as dot-notation paths rooted at the replay payload, for example ['events.0.timestamp', 'meta.uuid'].

emitSymbolBaseline also accepts { bundlePath, outputPath } for bundle-driven baseline generation when the caller is not operating on a live v4 workspace.

Plus per-tier helpers (checkImportGraph, checkModuleLoad, checkSymbolDiff, checkReplay) for callers that want one tier. createEquivExecutionContext() plus the check*WithContext() variants are also exported for callers that want to reuse one shared boot/analysis cache across multiple tier calls in the same process.

Error behavior:

  • runEquiv() catches unexpected tier crashes and records them as red tier results so the overall report still renders.
  • Standalone tier helpers still throw for invalid input/options and unexpected setup failures. They return an EquivCheckResult only after the tier has started running normally.
  • check*WithContext exports exist for callers that want to reuse one EquivExecutionContext across multiple tier invocations in the same process.

CLI

ushman-equiv <workspace> [--tiers=I,L,S,R | --tier=I] [--filter=<glob>]
                         [--entrypoint=<path>] [--baseline=<path>]
                         [--fixtures=<dir>] [--modules=<dir>]
                         [--src-roots=<comma-list>] [--mode=preview|dev]
                         [--write-result] [--json]
                         [--max-concurrency=<n>]

ushman-equiv emit-baseline [<workspace> | --workspace=<path>] [--out=<path>]
ushman-equiv --version

Exit codes:

  • 0: verdict is green or yellow
  • 1: verdict is red
  • 2: equiv runtime / CLI error

--mode=preview is the authoritative default for tiers L and R; --mode=dev is the faster smoke path. --write-result writes <workspace>/.lab/equiv/result.json atomically. --filter matches fixture names for tier R, symbol names for tier S, and relative source-file paths for tier I. --baseline may point at a workspace-relative or absolute baseline file. --max-concurrency is capped at 64.

Defaults for v4 workspaces:

  • Tier S baseline: <workspace>/.lab/equiv/baseline.json
  • Tier R fixtures: <workspace>/.lab/characterize/replay/
  • Tier R fallback modules: <workspace>/.lab/characterize/modules/

Relevant environment overrides:

  • USHMAN_EQUIV_NODE_BINARY: override the Node binary used for Tier L child-process module loading when the parent process is not plain Node.
  • USHMAN_EQUIV_MODULE_LOAD_TIMEOUT_MS: cap Tier L child-process runtime.
  • USHMAN_EQUIV_BOOT_TIMEOUT_MS, USHMAN_EQUIV_BUILD_TIMEOUT_MS, USHMAN_EQUIV_MAX_LOG_BYTES: tune preview/dev boot behavior.
  • USHMAN_EQUIV_BOOT_PORT_RETRY_LIMIT: retry strict-port preview/dev boot when the chosen port loses a race to another local process.

Internal execution notes for contributors:

  • Tier orchestration uses a shared execution context so Tier L and Tier R reuse the same boot smoke result during runEquiv().
  • Import-graph and symbol analysis are memoized per workspace/entrypoint/source-root set, then filtered per tier request.
  • Tier L delivers one shared vendor-stub helper module into the child runtime so large bare-specifier graphs do not duplicate the proxy factory in every generated stub.
  • Candidate boot still uses strict ports for deterministic probing, but it now retries EADDRINUSE contention with fresh ports before failing.

v3 workspaces are refused with the standard v4 cutover hint:

This workspace is in v3 layout (legacy stages/, .ushman/, handoff.json at root).
ushman v4 no longer ships the v3 layout readers or the live migrator.
`ushman migrate-v3-v4` is retained only as a diagnostic stub.
All known v3 workspaces were migrated during the v4 cutover.
If this workspace was not on that migration list, restore shibuk v2.x + ushman v3.x to migrate it first.
Workspace: <workspace>

This package does not ship the migrator itself. The migration is owned by the main ushman CLI.

Examples:

ushman-equiv ./candidate --tier=R --filter='clamp*'
ushman-equiv ./candidate --tier=I --filter='src/**/math/*.js'
ushman-equiv ./candidate --tier=S --filter='/^Game/'

Replay fixture shape:

{
  "fn": "clamp",
  "module": ".lab/characterize/modules/clamp.mjs",
  "calls": [
    { "args": [-1, 0, 10], "return": 0 },
    { "args": [4, 0, 10], "return": 4 }
  ]
}

module is optional. When present, it is resolved relative to the workspace root. When omitted, Tier R falls back to <workspace>/.lab/characterize/modules/<sanitized-fn>.mjs. thisArg and threw are also supported in calls when characterize captured a bound-method invocation or an expected throw.

Workspace-relative path resolution is validated twice:

  • lexical path containment under the workspace root
  • realpath containment under the workspace's real root, including the nearest existing ancestor for future output paths

This rejects symlink escapes while still allowing symlinks that resolve back inside the workspace.

Advanced replay knobs:

  • fixturesDir: override the default .lab/characterize/replay/ directory.
  • modulesDir: override the fallback replay-module directory.
  • maxConcurrency: cap fixture replay fan-out. The CLI enforces a maximum of 64.

Why This Exists Separate From ushman

ushman-equiv runs in the same pure-Node LLM sandbox and operator-side handoff flow as @ushman/verify, but it answers a different question. verify proves the candidate still parses and references sane files. equiv proves the refactor still resolves, loads, preserves required symbols, and reproduces captured outputs.

Where This Fits In The Family

| | | |---|---| | Runs after | @ushman/verify preflight | | Reuses output from | @ushman/characterize replay fixture generation | | Runs before | operator-side parity / merge acceptance | | Does not run | browsers, screenshots, or networked validation |

Safety Boundary

Tiers L and R execute workspace modules inside Node. Run ushman-equiv only against operator-controlled workspaces and handoff trees you trust to execute locally.