Skip to content

Package map

Argus is a pnpm workspace. Each package has one job and one rule.

Package Role Rule
@argus/core Pure domain types, ports, result-protocol parser, Hermes version/pin/asset logic No adapter or runtime imports — not even node:path
@argus/framework Runs inside Hermes: globals, runner, matchers, mocks, result emission Protect the result channel
@argus/rntl Synchronous component-testing facade, exposed through the argus alias A replaceable stopgap, maintained separately
@argus/esbuild Bundles polyfills + framework + tests into one IIFE Owns syntax lowering and the virtual entry
@argus/hermes Spawns the standalone VM, resolves engines, downloads prebuilts, builds from source Never use stdin — stdin puts Hermes in REPL mode
@argus/sourcemap Remaps Hermes stack frames back to original sources Must be total: never throw during reporting
@argus/reporter-cli Terminal output and exit-code policy Report test failures separately from infra failures
@argus/cli Composition root Wires adapters; keeps the domain pure

@argus/core holds things two sides must agree on exactly:

  • Hermes tag parsing. The provisioning chain and the release pipeline must derive the same identity from the same ref, or a release is published under one name and downloaded under another.
  • On-disk layout. The source-build adapter writes the cache; the provisioning chain reads it. Duplicated path segments drift into a cache written to one path and looked up at another.
  • Asset names and release notes. CI publishes the assets, the chain downloads them. The one place that knows what an asset is called is the one place that describes it — which is also why the release body is generated by a function with a test, not inlined in YAML.

Paths are expressed as segments, not joined strings, because core may not import node:path. Callers join them with their platform’s separator.

@argus/framework is the only package that runs inside Hermes. Everything about it follows from that:

  • Bundled, never resolved at run time.
  • Constrained to the syntax envelope.
  • Index loops and captured primordials in the reporting path (why).

Host-side packages are ordinary Node and have none of these constraints. Do not carry framework discipline into the CLI, and do not carry CLI habits into the framework.

@argus/cli and @argus/reporter-cli have zero external runtime dependencies. That is deliberate: for a tool whose pitch is engine fidelity at unit-test cost, a small install is part of the argument.

Node’s built-ins cover more than they used to:

Need Built-in
Argument parsing node:util.parseArgs
Colour, with NO_COLOR / FORCE_COLOR handling node:util.styleText
Glob discovery fs.promises.glob
Loading a TypeScript config Native type stripping

The only external runtime dependencies in the whole workspace are esbuild (the bundler), source-map (isolated in @argus/sourcemap), Babel (legacy class lowering only), and React plus test-renderer inside the optional component-testing package.

Every added dependency needs a reason a built-in cannot satisfy.

Files stay at or below roughly 500 lines; modules get split when they cross it. Precedent: matchers.ts became matchers.ts + deep-equal.ts + show.ts + async-matchers.ts + expect-state.ts; the runner’s helpers became jest-api.ts + hooks.ts.