@as-harness/cli
v0.6.0
Published
The CLI package compiles AssemblyScript test files to Wasm, selects a harness, and executes tests. The repo authors it in Bun/TypeScript, publishes it through npm, and also proves a Node-targeted source-host bundle path.
Readme
@as-harness/cli
The CLI package compiles AssemblyScript test files to Wasm, selects a harness, and executes tests. The repo authors it in Bun/TypeScript, publishes it through npm, and also proves a Node-targeted source-host bundle path.
Public installable distribution is npm-only. The published CLI expects
assemblyscript to be installed by the consuming project as a peer dependency.
Today
listdiscovers test entries.runcompiles and runs entries.run --coverageemits merged coverage intext,json,yaml,csv,lcov, orcobertura.--coverage-include,--coverage-exclude, and repeated--coverage-point-typerefine instrumentation.--update-snapshotsis the explicit rewrite path for host-owned snapshot artifacts.- compile-wrapper rewriting of bare
abort(...)/trace(...)emits structured hostdebugevents without requiring explicit user--usewiring. --harnessaccepts built-in aliases plus project-local path and package-based custom runtimes.- root
bun testand release smoke flows now reuse package-local host commands (npm testper host). - source-host verification builds a Node-targeted CLI bundle with Bun and runs
that bundle under the Node baseline from
.mise.toml.
Remaining Limits
- async/Promise-based guest APIs remain unsupported
- thin adapters stay intentionally narrow
Runtime Model
- CLI compiles AssemblyScript with bundled guest libraries.
- It hands Wasm bytes to one selected host runtime.
- The host runs
start()via the shared runner contract.
The host contract is Runtime in types.ts. The wire ABI is docs/003-2026-03-17-harness-abi.md.
Report Semantics
Default reporting summarizes:
- counts, passes/failures, and diagnostics
- planner status from
discoveryOk,planningOk, andworkerCount - blocked runs rendered as
missing prerequisite,blocked by prerequisite,dependency cycle,invalid constraint, andstopped after failure - unsupported hint values rendered as informational
ignored hintplanner issues without changing pass/fail status - shared run metadata is a required
start()snapshot that mirrors the top-level summary fields and keeps the underlying planner code plus the concise issue label onplanIssuesandblocked - structured
debugdetails for rewrittenabort/traceevents, including crumb and location context when provided by the host - coverage after execution (when enabled)
Bundled Libraries
as-harness: native scheduler-aware declarations,sequential(...)groups, chainabledependsOn(...)handles, host-ownedinBand(...)/bail(...)/continueOnFailure(...)hints, and sharedTestContext.assert.ava: sync flattest(...)declarations, hooks,test.macro(...)plus explicituse(...)/useNamed(...)lowering helpers, adapter-localExecutionContext, andtest.metaplaceholders.uvu: sync top-leveltesthooks, root and suite-local host-ownedinBand(...)/bail(...)/continueOnFailure(...)hints,suite(...)builder objects,exec(bail?)root hint lowering,.run()no-op under host-owned execution, and adapter-localTestContextcrumbs with__suite__/__test__.uvu/assert: shared assertion surface:Assertion,ok,is,equal,match,type,instance,throws,snapshot,fixture,not,is.not,not.equal,not.match,not.type,not.instance,not.throws, andunreachable.jasmine: sync declarations, focus/exclude aliases, core hooks,fail(...), and a narrow shared matcher slice.jest: thin sync declarations + shared assertion set (containment, length/size, numeric,toThrow, strict equality helpers).mocha: sync BDD declarations, core hooks,only/skip/x*aliases, pending by omitted callback, and optional sharedTestContextcallbacks for diagnostics and assertions.qunit: sync default-exportedQUnitroot methods plus namedtest/modulemodifier exports, root and module hooks, runnabletodo(...)lowering, and the shippedAssertsubset with step verification.tap: sync default-exported root declarations and hooks, named root helpers, nestedt.test(...)subtests, per-test hooks,plan(...),end(),comment(...),teardown(...), and the shipped assertion subset.tape: sync default-exportedtest(...)declarations withonly/skip, nestedt.test(...),plan(...),end(),teardown(...),comment(...), and the shipped alias-heavy assertion subset.vitest: sync declarations, sharedsequentialconstraints, host-defaultconcurrentaliases,fails,skipIf/runIf,assertType(...), and the same shared matcher set.node:test: sync declarations, hooks,dependsOn(...), and the same host-owned planning hints.
See their interface docs:
- docs/013-2026-03-22-jasmine-adapter-interface.md
- docs/005-2026-03-17-jest-adapter.md
- docs/012-2026-03-22-mocha-adapter-interface.md
- docs/017-2026-03-22-ava-adapter-interface.md
- docs/020-2026-03-23-qunit-adapter-interface.md
- docs/019-2026-03-23-tap-adapter-interface.md
- docs/018-2026-03-22-tape-adapter-interface.md
- docs/014-2026-03-22-uvu-adapter-interface.md
- docs/021-2026-03-23-uvu-assertion-class-contract.md
- docs/008-2026-03-19-vitest-adapter.md
Built-In Harnesses
js: portable baseline host.wazero: Go native host via Node-API, published as@as-harness/wazeroplus per-platform binary packages.wasmtime: Rust native host via Node-API, published as@as-harness/wasmtimeplus per-platform binary packages.
Source-host proof is a separate path: the source-host matrix builds a
Node-targeted CLI bundle with Bun, executes that bundle under Node 25.8.1,
and uses AS_HARNESS_SOURCE_CLI_REPO_DIR so the bundled CLI still resolves the
repo-local wazero and wasmtime host packages during CI smoke.
Custom Harnesses
--harness now accepts three selector classes:
- built-in aliases:
js,wazero,wasmtime - filesystem paths resolved from the invocation cwd
- package specifiers resolved from the consuming project's dependency graph
Built-in aliases win before package resolution, so external packages cannot
shadow js, wazero, or wasmtime.
Accepted custom module shapes, in priority order:
defaultexport object withcreateHarness(...)- named
runtimeexport object withcreateHarness(...) - module namespace exposing
createHarness(...)directly
Required field:
createHarness(bytes, options?)
Optional fields:
name: override the CLI display name used in pass/fail summariesmutateCompilerArguments(args): append compile-time flags on top of the shipped default JS wrapper contract
Example:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const { createHarness } = require("@as-harness/js");
export default {
name: "custom-js",
createHarness,
};Compatibility rule:
- custom
.tsharness modules are supported only when the CLI itself is running on Bun - the Node-targeted source-host bundle supports custom
.js,.cjs, and.mjsruntime modules and rejects.tsselectors with an explicit Bun-only diagnostic
Commands
npm install -D assemblyscript @as-harness/cli
npx as-harness run ./example.test.tscd cli
bun install
bun run dev -- help
bun run dev -- run ./example.test.ts
bun run dev -- run --harness js --coverage ./example.test.ts
bun run dev -- run --harness ./tools/custom-harness.mjs ./example.test.ts
bun run dev -- run --harness @scope/custom-harness ./example.test.ts
bun run dev -- run --update-snapshots ./example.test.tsbun run host:matrix
bun run verify:source-hosts -- --target linux-x64 --report-dir ./dist/source-host-reports
cd harness/js && npm test
cd harness/wazero && npm test
cd harness/wasmtime && npm testTroubleshooting
- discovery failures: check glob/ignore inputs.
- compile failures: inspect AS diagnostics.
AssemblyScript is required...: installassemblyscriptalongside@as-harness/cliin the consuming project.- harness selection failures: confirm
--harness, installed host packages, and that direct custom.tsselectors are running on Bun. - source-host native failures on Windows: verify the generated Node-targeted source bundle path before narrowing the issue to the native host addon.
