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

184 lines
7.4 KiB
TypeScript

/**
* Tests for agentbbs MCP tools (ADR-164 Phase 1).
*
* Two surfaces under test:
* 1. STRUCTURAL — exposure, schema, validation. Runs regardless of agentbbs presence.
* 2. HAPPY PATH — gated on agentbbs being importable via it.skipIf(!havePkg).
*
* The degraded path is exercised structurally: when agentbbs is missing,
* every handler returns `{degraded: true, reason: 'agentbbs-not-found'}`
* matching the metaharness / agenticow / testgen contract.
*/
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { agentbbsTools } from '../src/mcp-tools/agentbbs-tools.js';
function findTool(name: string) {
const t = agentbbsTools.find(t => t.name === name);
if (!t) throw new Error(`tool not found: ${name}`);
return t;
}
// Detect agentbbs availability at module scope so it.skipIf evaluates correctly.
let havePkg = false;
try { await import('agentbbs'); havePkg = true; } catch { havePkg = false; }
describe('agentbbs MCP tools — structural contract', () => {
it('exposes exactly 4 tools (register / publish / watch / human_join)', () => {
const names = agentbbsTools.map(t => t.name).sort();
expect(names).toEqual([
'federation_bbs_human_join',
'federation_bbs_publish',
'federation_bbs_register',
'federation_bbs_watch',
]);
});
it('every tool has an object inputSchema with handler + ≥80-char description', () => {
for (const t of agentbbsTools) {
expect(t.inputSchema.type).toBe('object');
expect(t.inputSchema.properties).toBeDefined();
expect(typeof t.handler).toBe('function');
expect(t.description.length).toBeGreaterThanOrEqual(80);
// ADR-112 — descriptions must carry "Use when ... is wrong because ..." guidance.
expect(t.description).toMatch(/Use when/i);
expect(t.description).toMatch(/wrong because/i);
}
});
it('register rejects path traversal in basePath', async () => {
const register = findTool('federation_bbs_register');
await expect(register.handler({
basePath: '../../../../etc/passwd',
roomLabel: '#sales',
})).rejects.toThrow(/disallowed characters/);
});
it('register rejects an illegal roomLabel', async () => {
const register = findTool('federation_bbs_register');
await expect(register.handler({
roomLabel: 'evil; rm -rf /',
})).rejects.toThrow(/may only contain/);
});
it('register accepts conventional #-prefixed room labels', async () => {
// Even when agentbbs is missing we should validate inputs first OR degrade
// — but the contract is: validation errors must surface as throws.
// With agentbbs missing we get a degraded result instead of validation.
// So this test only meaningfully covers regex acceptance shape.
expect(/^[A-Za-z0-9_.\-:/@#]+$/.test('#sales')).toBe(true);
expect(/^[A-Za-z0-9_.\-:/@#]+$/.test('finance')).toBe(true);
expect(/^[A-Za-z0-9_.\-:/@#]+$/.test('hr/onboarding')).toBe(true);
});
it('publish rejects malformed msgType (validation runs before optional-dep check)', async () => {
const publish = findTool('federation_bbs_publish');
await expect(publish.handler({
roomId: 'sales-12345678',
msgType: 'bad type with spaces',
payload: {},
})).rejects.toThrow(/msgType must be alnum/);
});
it('publish rejects non-object payload', async () => {
const publish = findTool('federation_bbs_publish');
await expect(publish.handler({
roomId: 'sales-12345678',
msgType: 'task-result',
payload: 'not an object',
})).rejects.toThrow(/payload must be a JSON object/);
});
it('all 4 tools return {degraded:true, reason:"agentbbs-not-found"} when agentbbs is missing', async () => {
if (havePkg) return; // happy-path case is covered elsewhere
for (const t of agentbbsTools) {
const minimalInput: Record<string, unknown> =
t.name === 'federation_bbs_register' ? { roomLabel: '#sales' } :
t.name === 'federation_bbs_publish' ? { roomId: 'sales-12345678', msgType: 'task-result', payload: {} } :
t.name === 'federation_bbs_watch' ? { roomId: 'sales-12345678' } :
t.name === 'federation_bbs_human_join' ? { roomId: 'sales-12345678' } :
{};
const r: any = await t.handler(minimalInput);
expect(r.success).toBe(true);
expect(r.degraded).toBe(true);
expect(r.reason).toBe('agentbbs-not-found');
}
});
});
describe('agentbbs MCP tools — happy path (real package)', () => {
let workdir: string;
let roomId: string;
beforeAll(() => {
workdir = mkdtempSync(join(tmpdir(), 'agentbbs-tools-'));
});
afterAll(() => {
try { rmSync(workdir, { recursive: true, force: true }); } catch { /* ignore */ }
});
it.skipIf(!havePkg)('register: creates a room and persists registry', async () => {
const register = findTool('federation_bbs_register');
const r: any = await register.handler({ basePath: workdir, roomLabel: '#sales' });
expect(r.success).toBe(true);
expect(r.degraded).toBeUndefined();
expect(r.trustLevel).toBe('attested');
expect(r.roomId).toMatch(/^sales-[0-9a-f]{8}$/);
expect(r.nodeId).toMatch(/^[0-9a-f]{16}$/);
roomId = r.roomId;
const reg = JSON.parse(readFileSync(join(workdir, 'rooms.json'), 'utf-8'));
expect(reg[roomId]).toBeDefined();
expect(reg[roomId].roomLabel).toBe('#sales');
});
it.skipIf(!havePkg)('publish: writes a ReplicateMessage envelope to the room log', async () => {
const publish = findTool('federation_bbs_publish');
const r: any = await publish.handler({
basePath: workdir,
roomId,
msgType: 'task-result',
payload: { agent: 'lead-gen', leadsQualified: 3 },
});
expect(r.success).toBe(true);
expect(r.degraded).toBeUndefined();
expect(r.envelopeId).toBeTruthy();
expect(r.recipientHopCount).toBe(0);
expect(existsSync(join(workdir, `room-${roomId}.jsonl`))).toBe(true);
});
it.skipIf(!havePkg)('watch: returns envelopes from the room log with monotonic seq', async () => {
const watch = findTool('federation_bbs_watch');
const r: any = await watch.handler({ basePath: workdir, roomId, limit: 50 });
expect(r.success).toBe(true);
expect(r.envelopes.length).toBeGreaterThan(0);
// Seq must be strictly monotonic
let lastSeq = 0;
for (const e of r.envelopes) {
expect(e.seq).toBeGreaterThan(lastSeq);
lastSeq = e.seq;
}
});
it.skipIf(!havePkg)('human_join: mints a single-use Ed25519-signed token that expires in the future', async () => {
const join = findTool('federation_bbs_human_join');
const before = Date.now();
const r: any = await join.handler({ roomId: 'sales-12345678', ttlSeconds: 120 });
const after = Date.now();
expect(r.success).toBe(true);
expect(r.degraded).toBeUndefined();
expect(r.handshakeToken).toBeTruthy();
expect(r.handshakeToken.length).toBeGreaterThan(50);
expect(r.webUrl).toMatch(/^https:\/\/agentbbs\.local\//);
expect(r.sshCommand).toMatch(/^ssh /);
const expiresAt = new Date(r.expiresAt).getTime();
expect(expiresAt).toBeGreaterThan(before);
// Expiry must be ≤ ttlSeconds from now (within a wide margin to absorb scheduling jitter).
expect(expiresAt - after).toBeLessThanOrEqual(120 * 1000 + 1000);
expect(expiresAt - before).toBeGreaterThanOrEqual(120 * 1000 - 1000);
});
});