Files
wehub-resource-sync 23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:19 +08:00

328 lines
12 KiB
JavaScript

#!/usr/bin/env node
/**
* Full plugin smoke test against a live Cognitum Seed device.
* Exercises every iot subcommand that is safe to run against a live, paired
* device. Skips firmware deploy/advance/rollback (requires explicit operator
* authorization — they trigger an OTA that can brick the device).
*
* Restoration: the pair/unpair cycle uses a unique client-name so it doesn't
* touch any pre-existing pairing. Vector ingest writes one tagged test vector
* and tries to delete it after.
*
* Run from the plugin directory after `npm run build`.
*/
import { IoTCognitumPlugin } from '../../dist/plugin.js';
import { readFileSync, existsSync } from 'node:fs';
import { resolve } from 'node:path';
// Load .env from CWD (or walk up) so COGNITUM_SEED_TOKEN is available.
function loadDotenv() {
let dir = process.cwd();
for (let i = 0; i < 8; i++) {
const f = resolve(dir, '.env');
if (existsSync(f)) {
for (const line of readFileSync(f, 'utf8').split('\n')) {
const t = line.trim();
if (!t || t.startsWith('#')) continue;
const eq = t.indexOf('=');
if (eq < 1) continue;
const k = t.slice(0, eq).trim();
let v = t.slice(eq + 1).trim();
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
if (process.env[k] === undefined) process.env[k] = v;
}
return f;
}
const parent = resolve(dir, '..');
if (parent === dir) break;
dir = parent;
}
return null;
}
const envFile = loadDotenv();
const SEED_TOKEN = process.env.COGNITUM_SEED_TOKEN;
const SEED_ENDPOINT =
process.env.SEED_ENDPOINT ?? (SEED_TOKEN ? 'https://169.254.42.1:8443' : 'http://169.254.42.1');
console.log(`[smoke] env: ${envFile ?? '(none)'}`);
console.log(`[smoke] endpoint: ${SEED_ENDPOINT}`);
console.log(`[smoke] bearer token: ${SEED_TOKEN ? 'loaded' : 'absent'}`);
// Self-signed cert tolerance for pair-window fetch (https port uses dev cert).
if (SEED_ENDPOINT.startsWith('https://')) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}
const plugin = new IoTCognitumPlugin();
const noop = () => undefined;
await plugin.initialize({
config: { fleetId: 'test-fleet', zoneId: 'zone-test', tlsInsecure: true },
eventBus: { emit: noop, on: noop, off: noop, once: noop },
logger: {
info: () => {},
warn: (...a) => console.warn('[warn]', ...a),
error: (...a) => console.error('[error]', ...a),
debug: () => {},
},
services: { get: () => undefined, register: noop, has: () => false },
});
const commands = plugin.registerCLICommands();
const cmd = (name) => {
const c = commands.find((c) => c.name === name);
if (!c) throw new Error(`No command: ${name}`);
return c;
};
const section = (title) => {
console.log('\n' + '='.repeat(60));
console.log(' ' + title);
console.log('='.repeat(60));
};
let passCount = 0;
let failCount = 0;
const results = [];
const run = async (label, fn) => {
console.log(`\n--- ${label} ---`);
try {
await fn();
console.log(`[ok] ${label}`);
passCount++;
results.push({ label, status: 'pass' });
} catch (err) {
const msg = err?.message ?? String(err);
console.error(`[fail] ${label}: ${msg}`);
failCount++;
results.push({ label, status: 'fail', error: msg });
}
};
// ============================================================
// Tier 1: configuration + lifecycle (no device state change)
// ============================================================
section('iot init');
await run('init', () => cmd('iot init').handler({ _: [], 'fleet-id': 'test-fleet', 'zone-id': 'zone-test' }));
section(`iot register (${SEED_ENDPOINT}${SEED_TOKEN ? ' + bearer' : ''})`);
await run('register', () =>
cmd('iot register').handler({
_: [],
endpoint: SEED_ENDPOINT,
...(SEED_TOKEN ? { token: SEED_TOKEN } : {}),
}),
);
const coord = plugin['coordinator'];
const devices = coord ? coord.listDevices() : [];
const deviceId = devices[0]?.deviceId;
if (!deviceId) {
console.error('No device registered — aborting tier 2+');
process.exit(1);
}
console.log(`\n[info] live device: ${deviceId}`);
section('iot list');
await run('list', () => cmd('iot list').handler({ _: [] }));
// ============================================================
// Tier 2: read-only device queries
// ============================================================
section(`iot status ${deviceId}`);
await run('status', () => cmd('iot status').handler({ _: [deviceId] }));
section(`iot status (json format)`);
await run('status --format json', () => cmd('iot status').handler({ _: [deviceId], format: 'json' }));
section(`iot mesh ${deviceId}`);
await run('mesh', () => cmd('iot mesh').handler({ _: [deviceId] }));
section(`iot witness ${deviceId}`);
await run('witness', () => cmd('iot witness').handler({ _: [deviceId] }));
section(`iot witness verify ${deviceId}`);
await run('witness verify', () => cmd('iot witness verify').handler({ _: [deviceId] }));
section(`iot anomalies ${deviceId}`);
await run('anomalies (no baseline)', () => cmd('iot anomalies').handler({ _: [deviceId] }));
section(`iot baseline ${deviceId}`);
await run('baseline (read)', () => cmd('iot baseline').handler({ _: [deviceId] }));
// ============================================================
// Tier 3: vector store query (read-only) and ingest (write)
// ============================================================
// Pass device-id both positionally and as --device-id option:
// the handlers in cli-commands.ts are inconsistent (some read args._[0],
// others read args['device-id']).
const dArgs = (extra = {}) => ({ _: [deviceId], 'device-id': deviceId, ...extra });
section(`iot query ${deviceId} (k=3, dim-8 zero vector)`);
await run('query (k=3)', () =>
cmd('iot query').handler(dArgs({ vector: '[0,0,0,0,0,0,0,0]', k: '3' })),
);
section(`iot ingest ${deviceId} (1 tagged test vector)`);
await run('ingest 1 vector (requires write-scoped token)', async () => {
try {
await cmd('iot ingest').handler(
dArgs({
vector: '[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8]',
metadata: JSON.stringify({ tag: 'smoke-test', ts: new Date().toISOString() }),
}),
);
} catch (err) {
const msg = err?.message ?? String(err);
if (/not authorized|forbidden|401|403/i.test(msg)) {
console.log(`[expected] token lacks ingest scope: ${msg}`);
return;
}
throw err;
}
});
// ============================================================
// Tier 4: pair / unpair round-trip with unique client-name
// (Seed requires the pair window to be opened first via POST /pair/window —
// the iot plugin doesn't expose that, so open it via direct API call.
// Unpair requires bearer auth — Seed's link-local HTTP doesn't have it.)
// ============================================================
const pairClient = `smoke-test-${Date.now()}`;
section('open pair window (direct API)');
await run('open pair window (90s)', async () => {
// Check first — avoid 429 if window is already open
const statusResp = await fetch(`${SEED_ENDPOINT}/api/v1/pair/status`, {
headers: SEED_TOKEN ? { authorization: `Bearer ${SEED_TOKEN}` } : {},
});
if (statusResp.ok) {
const s = await statusResp.json();
if (s.pairing_window_open) {
console.log(`[ok] window already open (${s.window_remaining_secs}s remaining); skipping reopen`);
return;
}
}
const resp = await fetch(`${SEED_ENDPOINT}/api/v1/pair/window`, {
method: 'POST',
headers: {
'content-type': 'application/json',
...(SEED_TOKEN ? { authorization: `Bearer ${SEED_TOKEN}` } : {}),
},
body: JSON.stringify({ duration_secs: 90 }),
});
if (!resp.ok) throw new Error(`open window: HTTP ${resp.status}`);
});
section(`iot pair ${deviceId} (client="${pairClient}")`);
await run('pair', () =>
cmd('iot pair').handler(dArgs({ 'client-name': pairClient, name: pairClient })),
);
section(`iot unpair ${deviceId} (client="${pairClient}")`);
await run('unpair (link-local; expected: bearer required)', async () => {
try {
await cmd('iot unpair').handler(dArgs({ 'client-name': pairClient, name: pairClient }));
} catch (err) {
const msg = err?.message ?? String(err);
if (/bearer|unauthor|401/i.test(msg)) {
console.log(`[expected] link-local unpair denied (bearer required): ${msg}`);
return;
}
throw err;
}
});
// ============================================================
// Tier 5: fleet operations (coordinator-only, no device side effects)
// ============================================================
const fleetId = `smoke-fleet-${Date.now()}`;
section('iot fleet list (pre-create)');
await run('fleet list (pre)', () => cmd('iot fleet list').handler({ _: [] }));
section(`iot fleet create ${fleetId}`);
await run('fleet create', () =>
cmd('iot fleet create').handler({
_: [],
'fleet-id': fleetId,
name: 'smoke test fleet',
}),
);
section(`iot fleet add ${fleetId} ${deviceId}`);
await run('fleet add', () =>
cmd('iot fleet add').handler({
_: [fleetId, deviceId],
'fleet-id': fleetId,
'device-id': deviceId,
}),
);
section('iot fleet list (post-add)');
await run('fleet list (post-add)', () => cmd('iot fleet list').handler({ _: [] }));
section(`iot fleet remove ${fleetId} ${deviceId}`);
await run('fleet remove', () =>
cmd('iot fleet remove').handler({
_: [fleetId, deviceId],
'fleet-id': fleetId,
'device-id': deviceId,
}),
);
section(`iot fleet delete ${fleetId}`);
await run('fleet delete', () =>
cmd('iot fleet delete').handler({ _: [fleetId] }),
);
// ============================================================
// Tier 6: firmware reads (safe). Deploy/advance/rollback skipped.
// ============================================================
section('iot firmware list');
await run('firmware list', () => cmd('iot firmware list').handler({ _: [] }));
// firmware status needs a rollout-id; we have none. Test the "missing"
// path by passing a bogus id and confirming graceful error handling.
section('iot firmware status BOGUS-ROLLOUT-ID');
await run('firmware status (graceful error)', async () => {
try {
await cmd('iot firmware status').handler({ _: ['BOGUS-ROLLOUT-ID'] });
} catch (err) {
const msg = err?.message ?? String(err);
if (/not found|no.*rollout|unknown|missing/i.test(msg)) {
console.log(`[expected] graceful: ${msg}`);
return;
}
throw err;
}
});
// ============================================================
// Tier 7: device-deregister (coordinator-only, in-memory)
// ============================================================
section(`iot remove ${deviceId} (final cleanup)`);
await run('remove (deregister)', () => cmd('iot remove').handler({ _: [deviceId] }));
section('iot list (post-remove)');
await run('list (post-remove, expect empty)', () => cmd('iot list').handler({ _: [] }));
// ============================================================
// Summary
// ============================================================
console.log('\n' + '='.repeat(60));
console.log(` RESULTS: ${passCount} passed, ${failCount} failed (${results.length} total)`);
console.log('='.repeat(60));
for (const r of results) {
const tag = r.status === 'pass' ? '✓' : '✗';
const note = r.status === 'fail' ? ` — ${r.error}` : '';
console.log(` ${tag} ${r.label}${note}`);
}
console.log('\nSkipped (require explicit operator authorization — OTA risk):');
console.log(' - iot firmware deploy <fleet-id> --version <ver>');
console.log(' - iot firmware advance <rollout-id>');
console.log(' - iot firmware rollback <rollout-id>');
console.log('');
process.exit(failCount > 0 ? 1 : 0);