181 lines
5.9 KiB
JavaScript
181 lines
5.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import os from 'node:os';
|
|
import { spawnSync } from 'node:child_process';
|
|
|
|
const packageRoot = path.resolve(import.meta.dirname, '..');
|
|
|
|
function createFixtureRoot() {
|
|
return fs.mkdtempSync(path.join(os.tmpdir(), 'reporting-governance-exports-'));
|
|
}
|
|
|
|
function installPackageAlias(root) {
|
|
const packageDir = path.join(root, 'node_modules', '@openclaw', 'plugin-reporting-governance');
|
|
fs.mkdirSync(path.dirname(packageDir), { recursive: true });
|
|
fs.symlinkSync(packageRoot, packageDir, 'dir');
|
|
return packageDir;
|
|
}
|
|
|
|
function writeState(root) {
|
|
const statePath = path.join(root, 'watchdog-state.json');
|
|
fs.writeFileSync(statePath, `${JSON.stringify({
|
|
version: 1,
|
|
watchdogs: [
|
|
{
|
|
id: 'reporting-governance-plugin-watchdog',
|
|
task: 'reporting-governance plugin spec development',
|
|
status: 'active',
|
|
ownerSessionKey: 'agent:coder:main',
|
|
reportChannel: 'telegram',
|
|
reportTarget: '864811879',
|
|
intervalMinutes: 10,
|
|
lastMilestoneAt: '2026-05-07T08:00:00.000Z',
|
|
lastAlertAt: null
|
|
}
|
|
]
|
|
}, null, 2)}\n`, 'utf8');
|
|
return statePath;
|
|
}
|
|
|
|
function runNodeEval(root, source, env = {}) {
|
|
return spawnSync(process.execPath, ['--input-type=module', '--eval', source], {
|
|
cwd: root,
|
|
encoding: 'utf8',
|
|
env: {
|
|
...process.env,
|
|
...env,
|
|
},
|
|
});
|
|
}
|
|
|
|
function runJsonEval(root, source, env = {}) {
|
|
const result = runNodeEval(root, source, env);
|
|
if (result.status !== 0) {
|
|
throw new Error(`node eval failed: ${(result.stderr ?? '').trim() || '(no stderr)'}`);
|
|
}
|
|
return JSON.parse((result.stdout ?? '').trim());
|
|
}
|
|
|
|
test('package root export resolves public package surface only', () => {
|
|
const root = createFixtureRoot();
|
|
try {
|
|
installPackageAlias(root);
|
|
const result = runJsonEval(root, `
|
|
import * as plugin from '@openclaw/plugin-reporting-governance';
|
|
process.stdout.write(JSON.stringify({
|
|
packageName: plugin.packageName,
|
|
hasRunWatchdogChain: typeof plugin.runWatchdogChain,
|
|
hasPlanDecisionExecution: typeof plugin.planDecisionExecution,
|
|
}));
|
|
`);
|
|
|
|
assert.equal(result.packageName, '@openclaw/plugin-reporting-governance');
|
|
assert.equal(result.hasRunWatchdogChain, 'function');
|
|
assert.equal(result.hasPlanDecisionExecution, 'function');
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('adapters subpath export resolves package-owned adapter index', () => {
|
|
const root = createFixtureRoot();
|
|
try {
|
|
installPackageAlias(root);
|
|
const result = runJsonEval(root, `
|
|
import * as adapters from '@openclaw/plugin-reporting-governance/adapters';
|
|
process.stdout.write(JSON.stringify({
|
|
adapterKeys: Object.keys(adapters).sort(),
|
|
}));
|
|
`);
|
|
|
|
assert.deepEqual(result.adapterKeys, [
|
|
'createRuntimeBinding',
|
|
'runBridgeSupervisorAdapter',
|
|
'runDispatcherAdapter',
|
|
'runOrchestratorAdapter',
|
|
'runSenderBindingAdapter',
|
|
'runWatchdogAdapter',
|
|
]);
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('deep runtime-binding subpath stays outside package exports boundary', () => {
|
|
const root = createFixtureRoot();
|
|
try {
|
|
installPackageAlias(root);
|
|
const result = runNodeEval(root, `
|
|
import('@openclaw/plugin-reporting-governance/src/adapters/runtime-binding.mjs')
|
|
.then(() => {
|
|
process.stdout.write(JSON.stringify({ ok: true }));
|
|
})
|
|
.catch((error) => {
|
|
process.stdout.write(JSON.stringify({
|
|
ok: false,
|
|
code: error?.code ?? null,
|
|
name: error?.name ?? null,
|
|
message: error?.message ?? null,
|
|
}));
|
|
});
|
|
`);
|
|
|
|
assert.equal(result.status, 0, result.stderr);
|
|
const payload = JSON.parse((result.stdout ?? '').trim());
|
|
assert.equal(payload.ok, false);
|
|
assert.equal(payload.code, 'ERR_PACKAGE_PATH_NOT_EXPORTED');
|
|
assert.equal(payload.name, 'Error');
|
|
assert.match(payload.message ?? '', /Package subpath '\.\/src\/adapters\/runtime-binding\.mjs' is not defined by "exports"/);
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('leaf subpath export resolves and can execute through injected runtime binding', () => {
|
|
const root = createFixtureRoot();
|
|
try {
|
|
installPackageAlias(root);
|
|
fs.mkdirSync(path.join(root, 'scripts'), { recursive: true });
|
|
fs.mkdirSync(path.join(root, 'events'), { recursive: true });
|
|
fs.mkdirSync(path.join(root, 'evidence'), { recursive: true });
|
|
fs.mkdirSync(path.join(root, 'queue'), { recursive: true });
|
|
const statePath = writeState(root);
|
|
|
|
const stubScriptPath = path.join(root, 'scripts', 'custom-watchdog.mjs');
|
|
fs.writeFileSync(stubScriptPath, `
|
|
process.stdout.write(JSON.stringify({
|
|
ok: true,
|
|
source: 'stub-watchdog',
|
|
argv: process.argv.slice(2),
|
|
}));
|
|
`, 'utf8');
|
|
|
|
const result = runJsonEval(root, `
|
|
import { runWatchdogAdapter } from '@openclaw/plugin-reporting-governance/adapters/watchdog';
|
|
const out = runWatchdogAdapter({
|
|
state: ${JSON.stringify(statePath)},
|
|
evidenceDir: ${JSON.stringify(path.join(root, 'evidence'))},
|
|
eventDir: ${JSON.stringify(path.join(root, 'events'))},
|
|
notificationDir: ${JSON.stringify(path.join(root, 'queue'))},
|
|
runtimeBinding: {
|
|
cwd: ${JSON.stringify(root)},
|
|
scripts: {
|
|
watchdog: ${JSON.stringify(stubScriptPath)},
|
|
},
|
|
},
|
|
now: '2026-05-07T08:20:00.000Z',
|
|
});
|
|
process.stdout.write(JSON.stringify(out));
|
|
`);
|
|
|
|
assert.equal(result.ok, true);
|
|
assert.equal(result.source, 'stub-watchdog');
|
|
assert.ok(result.argv.includes('--state'));
|
|
assert.ok(result.argv.includes(path.resolve(statePath)));
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|