v3/docs/adr/ADR-154-metaharness-kernel-platform-binaries.md
@metaharness/kernel per-platform NAPI-RS binaries: WASM-only at runtime, native fast-path unreachedStatus: Accepted (WASM-only path is functional; native fast-path tracked upstream)
Date: 2026-06-17
Related: ADR-150 (MetaHarness integration surfaces), ADR-153 (Darwin Mode integration), ADR-124 (optional native dependencies), ADR-148 (cost-optimal router lifecycle), ADR-152 (genome similarity)
Upstream: ruvnet/agent-harness-generator/packages/kernel-js
Affects: [email protected]+, @claude-flow/[email protected]+, [email protected]+
Affected packages: @metaharness/kernel@~0.1.0 (already in optionalDependencies per ADR-150)
ADR-150 integrated @metaharness/kernel@~0.1.0 as an optional peer of @claude-flow/cli (and transitively ruflo). The kernel exposes loadKernel(), kernelDiagnostics(), ToolDispatcher (claims-checked), SelfEvolvingRouter, TrajectoryStore, and rankWithDecay to ruflo's intelligence layer.
The upstream design intent (per packages/kernel-js/README.md) is:
At load time,
loadKernel()prefers the per-platform native package; falls back to wasm. The native packages (@metaharness/kernel-darwin-arm64,-linux-x64-gnu, etc.) are declared asoptionalDependencies— npm installs only the one for your platform.
@metaharness/[email protected]'s package.json declares five per-platform NAPI-RS native binaries as optionalDependencies:
{
"optionalDependencies": {
"@metaharness/kernel-darwin-arm64": "0.1.0",
"@metaharness/kernel-darwin-x64": "0.1.0",
"@metaharness/kernel-linux-x64-gnu": "0.1.0",
"@metaharness/kernel-linux-arm64-gnu": "0.1.0",
"@metaharness/kernel-win32-x64-msvc": "0.1.0"
}
}
None of the five per-platform binaries are published to npm:
@metaharness/kernel-darwin-arm64 NOT_PUBLISHED
@metaharness/kernel-darwin-x64 NOT_PUBLISHED
@metaharness/kernel-linux-x64-gnu NOT_PUBLISHED
@metaharness/kernel-linux-arm64-gnu NOT_PUBLISHED
@metaharness/kernel-win32-x64-msvc NOT_PUBLISHED
Runtime evidence — fresh install of [email protected] on a darwin-arm64 host (Mac mini M4 Pro, the platform the upstream-intended @metaharness/kernel-darwin-arm64 should serve):
$ npm install [email protected]
added 1163 packages
$ find node_modules/@metaharness/kernel-* -maxdepth 0 2>/dev/null
(no matches — none of the platform packages were resolved during install)
$ node -e "(await import('@metaharness/kernel')).loadKernel().then(k => console.log(k.backend))"
wasm
loadKernel() falls back to WASM cleanly. Functionality is intact; performance is the WASM tier, not the native tier the README advertises.
Accept the WASM-only runtime path as the supported configuration for ruflo 3.12.3+. Do not block on the upstream native-binary publish gap. Specifically:
@metaharness/kernel stays in optionalDependencies as it is today. loadKernel() already does the right thing — prefers native, falls back to WASM. The fallback is reached because the optional native packages don't resolve, which is the documented graceful path.plugins/ruflo-metaharness/scripts/smoke.sh that asserts loadKernel().backend === 'wasm' is reachable. This is the inverse of a regression check: if the upstream ever ships natives, the smoke alerts so we can re-baseline.@metaharness/kernel itself is uninstalled. The platform-binary absence is a softer degradation: kernel API surface is fully available, only the hot-path acceleration is missing.Three reasons:
loadKernel().backend === 'wasm' exposes the same API as the native backend. The router's SelfEvolvingRouter parallel-logging gate from ADR-150 Phase 2 works against the WASM kernel; ADR-152 §3.1 genome similarity is pure-TS and doesn't touch the kernel at all. No ruflo feature is blocked by the missing natives.ruvnet/agent-harness-generator (CI matrix → upload to npm). Ruflo can't ship the natives ourselves without forking — which would violate the "MetaHarness is first-party" framing from ADR-150.loadKernel() will silently pick them up on the next install. The smoke gate fires, we audit, and decide whether to re-baseline ruflo's perf docs.better-sqlite3, hnswlib-node, sharp et al: declare optional natives, ship a WASM/JS fallback, never crash when the native is absent.@metaharness/[email protected] introduces a new API that's native-only and silently no-ops in WASM, the smoke gate catches reachability but not behavioral parity. ADR-150 Phase 3 §3.4 (Capability Graph) is the right place to enforce per-API parity.Add to plugins/ruflo-metaharness/scripts/smoke.sh:
step "18a. @metaharness/kernel loadKernel returns wasm backend (ADR-153)"
miss=""
# Only run if kernel is installed (graceful per ADR-150 constraint #3)
if node -e "import('@metaharness/kernel').then(() => process.exit(0)).catch(() => process.exit(1))" 2>/dev/null; then
BACKEND=$(node --input-type=module -e "
const { loadKernel } = await import('@metaharness/kernel');
const k = await loadKernel();
process.stdout.write(k.backend || 'unknown');
" 2>/dev/null)
case "$BACKEND" in
wasm)
: # expected — see ADR-153
;;
native|napi|napi-rs)
# Upstream published the natives — re-baseline ruflo's perf docs
miss="$miss kernel-now-native-rebaseline-perf-docs"
;;
*)
miss="$miss kernel-unknown-backend:$BACKEND"
;;
esac
fi
[[ -z "$miss" ]] && ok || bad "$miss"
npx ruflo doctor --component metaharness should already report the kernel backend; verify that the JSON includes a kernelBackend: 'wasm' | 'native' | 'absent' field. If not, add it as part of the next doctor revision.
Wherever ruflo's perf docs cite kernel dispatch latency, add a one-liner:
Measured against
@metaharness/kernel's WASM path. NAPI-RS native binaries (@metaharness/kernel-{darwin-arm64,linux-x64-gnu,…}) are declared but not yet published upstream — see ADR-153.
@metaharness/kernel was first added as optionalDependency)@metaharness/router, parallel-logs via the kernel's SelfEvolvingRouter)ruvnet/agent-harness-generator for the per-platform publish (PR welcome, since the build matrix lives upstream)kernel-now-native-rebaseline-perf-docs. Action: re-run the relevant benchmarks, compare WASM vs NAPI-RS, update the docs with side-by-side numbers, drop the ADR's "currently inverted" caveat.@metaharness/kernel, not a native-binary publisher. If upstream stays unpublished for >1 quarter, revisit this decision.