Files
ruv b6f3abd35e feat(npm): ruview umbrella package + ESPHome radar source (ADR-376, ADR-373 A3)
- harness/ruview-umbrella -> npm `ruview` 0.8.0: one CLI and one MCP server
  for the operator harness, Homecore and the vitals kernel. `ruview homecore
  ...`, `ruview kernel <doctor|info|selftest|parity|synth|analyze|bench>`,
  `ruview capabilities`; everything else delegates to @ruvnet/ruview. MCP
  serves ruview_* + homecore_* tools and the ui:// console (stdio + HTTP).
- @ruvnet/ruview 0.8.0: bin renamed `ruview-harness` (the umbrella owns
  `ruview`; a clean tarball install showed the bin collision). New exports
  (cli, cli-ui, mcp, mcp-http, ui, esphome, kernel); injectable MCP handler;
  kernel as optional peer + setKernelImporter so the kernel resolves from
  the umbrella's tree under linked/pnpm installs.
- mmwave --source esphome: dependency-free read-only ESPHome native API
  client (private hosts only; encrypted/password APIs reported). Live Seeed
  MR60BHA2 kit: presence, distance, device-reported HR/BR (MEASURED).
- monitor detects Ameba CSI buffer starvation; radar views in terminal UI
  and console widget.
- homecore 0.1.0 and @ruvnet/ruview-kernel 0.1.0 gain ./cli exports.

Gates: harness 166 + 89 security, homecore 27 + 23, kernel 21 + 12,
umbrella 4; clean-dir tarball install smoke incl. live radar over HTTP MCP.
Local publish is a one-off exception to ADR-265 D2, recorded in ADR-376.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-10-01 16:30:23 -04:00

75 lines
4.0 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { importKernelPackage, kernelSelfTest, KERNEL_PACKAGE, setKernelImporter } from '../src/kernel.js';
import { authorizeTool } from '../src/policy.js';
import { runTool } from '../src/tools.js';
const fakeKernel = (overrides = {}) => ({
loadKernel: ({ backend }) => ({ backend: backend === 'auto' ? 'wasm' : backend, requestedBackend: backend, fallbackReason: backend === 'auto' ? 'no addon' : null, integrity: 'verified', sha256: 'ab' }),
selfTest: (kernel, { seconds }) => ({ ok: true, evidence: 'SYNTHETIC', backend: kernel.backend, seconds }),
...overrides,
});
test('kernel self-test fails closed when the optional package is absent', async () => {
const result = await kernelSelfTest({}, { importer: async () => { const e = new Error('nope'); e.code = 'ERR_MODULE_NOT_FOUND'; throw e; } });
assert.equal(result.ok, false);
assert.equal(result.reason, 'kernel_not_installed');
assert.match(result.remedy, /@ruvnet\/ruview-kernel/);
});
test('kernel self-test only imports the fixed package name', async () => {
const seen = [];
const result = await kernelSelfTest({ backend: 'auto', seconds: 45 }, { importer: async (s) => { seen.push(s); return fakeKernel(); } });
assert.deepEqual(seen, [KERNEL_PACKAGE]);
assert.equal(result.ok, true);
assert.equal(result.backend, 'wasm');
assert.equal(result.requestedBackend, 'auto');
assert.equal(result.fallbackReason, 'no addon');
assert.equal(result.seconds, 45);
assert.equal(result.evidence, 'SYNTHETIC');
});
test('kernel self-test reports load failures and incompatible packages honestly', async () => {
const failing = fakeKernel({ loadKernel: () => { const e = new Error('no addon'); e.code = 'backend_unavailable'; throw e; } });
const r1 = await kernelSelfTest({ backend: 'napi' }, { importer: async () => failing });
assert.deepEqual([r1.ok, r1.reason, r1.requestedBackend], [false, 'backend_unavailable', 'napi']);
const r2 = await kernelSelfTest({}, { importer: async () => ({}) });
assert.deepEqual([r2.ok, r2.reason], [false, 'kernel_incompatible']);
});
test('kernel tool is read-only for MCP and rejects module/path injection', async () => {
assert.equal(authorizeTool('ruview_kernel_selftest', {}, { source: 'mcp', grants: [] }).ok, true);
for (const args of [{ module: 'fs' }, { wasm_path: '/tmp/x.wasm' }, { backend: 'python' }, { seconds: 5 }]) {
const result = await runTool('ruview_kernel_selftest', args, { source: 'mcp' });
assert.equal(result.reason, 'invalid_arguments', JSON.stringify(args));
}
});
// Cross-package end-to-end (ADR-368). CI installs the packed
// @ruvnet/ruview-kernel tarball with `npm install --no-save` before this runs;
// elsewhere the package is optional and the fail-closed path is covered above.
let installed = false;
try { await import(KERNEL_PACKAGE); installed = true; } catch { /* optional */ }
test('installed kernel passes its SYNTHETIC self-test through the harness tool', { skip: !installed && `${KERNEL_PACKAGE} not installed` }, async () => {
const result = await runTool('ruview_kernel_selftest', { backend: 'wasm', seconds: 45 }, { source: 'mcp', grants: [] });
assert.equal(result.ok, true, JSON.stringify(result.checks));
assert.equal(result.backend, 'wasm');
assert.equal(result.evidence, 'SYNTHETIC');
assert.equal(result.integrity, 'verified');
});
test('an embedding package can supply the kernel importer (ADR-376)', async () => {
const seen = [];
setKernelImporter(async (specifier) => { seen.push(specifier); return { loadKernel: () => { throw Object.assign(new Error('stub'), { code: 'backend_unavailable' }); }, selfTest: () => ({}) }; });
try {
await importKernelPackage();
const r = await kernelSelfTest({ backend: 'wasm' });
assert.deepEqual(seen, [KERNEL_PACKAGE, KERNEL_PACKAGE]);
assert.equal(r.reason, 'backend_unavailable');
assert.throws(() => setKernelImporter('not a function'), /importer must be a function/);
} finally {
setKernelImporter((specifier) => import(specifier));
}
});