From d11ca9c31e35cef98fa752127c56e80c45ab2343 Mon Sep 17 00:00:00 2001 From: ruv Date: Sun, 24 May 2026 21:50:22 -0400 Subject: [PATCH] =?UTF-8?q?feat(adr-124/packaging):=20rename=20to=20@ruvne?= =?UTF-8?q?t/rvagent=200.1.0=20+=20manifest=20test=20(ADR-124=20=C2=A72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advances SPARC Phase 1 (Specification) for ADR-124 SENSE-BRIDGE by establishing the correct npm package identity that all subsequent implementation iters depend on. Changes: - tools/ruview-mcp/package.json - name: @ruv/ruview-mcp → @ruvnet/rvagent (ADR-124 §2.1) - version: 0.0.1 → 0.1.0 (initial publishable milestone) - removed private:true so the package is publishable (ADR-124 §2.6) - bin: added rvagent key alongside legacy ruview-mcp alias (ADR-124 §2.4) - exports: added "." entry with import+types keys for ESM+CJS dual output (ADR-124 §2.5) - files: added README.md and CHANGELOG.md slots (ADR-124 §5 npm publish plan) - keywords: expanded with sense-bridge, rvagent, ruvnet - repository / homepage / bugs: wired to github.com/ruvnet/RuView - tools/ruview-mcp/src/index.ts - SERVER_NAME: "ruview" → "rvagent" - PACKAGE_VERSION: "0.0.1" → "0.1.0" - stderr log prefix: [ruview-mcp] → [@ruvnet/rvagent] - tools/ruview-mcp/tests/manifest.test.ts (NEW) - 10 ADR-124 §2 acceptance-criterion assertions, all green - Guards name, version >=0.1.0, engines.node >=20, bin.rvagent, exports structure, publishConfig.access, @modelcontextprotocol/sdk dep, zod dep, ESM type, license Test results: 26/26 PASS (manifest.test.ts ×10 + tools.test.ts ×5 + validate.test.ts ×11) Build: tsc clean, zero errors. Next iter target: (A) Zod schema barrel for the 15+5 tool catalog from ADR-124 §4.1/4.1a Co-Authored-By: claude-flow --- tools/ruview-mcp/package.json | 33 ++++++-- tools/ruview-mcp/src/index.ts | 6 +- tools/ruview-mcp/tests/manifest.test.ts | 101 ++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 tools/ruview-mcp/tests/manifest.test.ts diff --git a/tools/ruview-mcp/package.json b/tools/ruview-mcp/package.json index 6eb55bc7..a36ea822 100644 --- a/tools/ruview-mcp/package.json +++ b/tools/ruview-mcp/package.json @@ -1,16 +1,25 @@ { - "name": "@ruv/ruview-mcp", - "version": "0.0.1", - "description": "RuView MCP server — expose WiFi-DensePose sensing capabilities as MCP tools for Claude Code, Cursor, and other MCP-compatible agents", - "private": true, + "name": "@ruvnet/rvagent", + "version": "0.1.0", + "description": "SENSE-BRIDGE: dual-transport MCP server (stdio + Streamable HTTP) exposing RuView WiFi-DensePose sensing primitives to AI agents", "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "types": "./dist/index.d.ts" + } + }, "bin": { + "rvagent": "dist/index.js", "ruview-mcp": "dist/index.js" }, "files": [ - "dist" + "dist", + "README.md", + "CHANGELOG.md" ], "scripts": { "build": "tsc", @@ -22,14 +31,26 @@ }, "keywords": [ "mcp", + "rvagent", "ruview", "wifi", "csi", "pose-estimation", - "cognitum" + "cognitum", + "sense-bridge", + "ruvnet" ], "author": "ruv ", "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/ruvnet/RuView.git", + "directory": "tools/ruview-mcp" + }, + "homepage": "https://github.com/ruvnet/RuView/tree/main/tools/ruview-mcp", + "bugs": { + "url": "https://github.com/ruvnet/RuView/issues" + }, "dependencies": { "@modelcontextprotocol/sdk": "^1.0.0", "zod": "^3.23.8" diff --git a/tools/ruview-mcp/src/index.ts b/tools/ruview-mcp/src/index.ts index e3e4afd1..64383873 100644 --- a/tools/ruview-mcp/src/index.ts +++ b/tools/ruview-mcp/src/index.ts @@ -43,8 +43,8 @@ import { jobStatus, } from "./tools/train-count.js"; -const PACKAGE_VERSION = "0.0.1"; -const SERVER_NAME = "ruview"; +const PACKAGE_VERSION = "0.1.0"; +const SERVER_NAME = "rvagent"; // ── Tool registry ────────────────────────────────────────────────────────── @@ -297,7 +297,7 @@ async function main(): Promise { // Log to stderr so it doesn't interfere with the MCP stdio protocol. process.stderr.write( - `[ruview-mcp] Server v${PACKAGE_VERSION} started. ` + + `[@ruvnet/rvagent] Server v${PACKAGE_VERSION} started. ` + `Sensing server: ${config.sensingServerUrl}\n` ); } diff --git a/tools/ruview-mcp/tests/manifest.test.ts b/tools/ruview-mcp/tests/manifest.test.ts new file mode 100644 index 00000000..c1fce4b8 --- /dev/null +++ b/tools/ruview-mcp/tests/manifest.test.ts @@ -0,0 +1,101 @@ +/** + * ADR-124 §2 manifest validation test. + * + * Guards that package.json satisfies every structural decision from ADR-124 §2: + * 1. Package name is @ruvnet/rvagent + * 2. Version is >= 0.1.0 + * 3. engines.node is >= 20 + * 4. bin includes the "rvagent" key (npx @ruvnet/rvagent invocation) + * 5. exports["." ] includes both "import" and "types" keys (ESM + types in tarball) + * 6. publishConfig.access === "public" (scoped package must be explicit) + * 7. @modelcontextprotocol/sdk is a runtime dependency (dual-transport server) + * 8. zod is a runtime dependency (input schema validation) + * 9. type === "module" (ESM-first, Node.js 20+ native) + * 10. license === "Apache-2.0" + */ + +import { readFileSync } from "node:fs"; +import { resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const pkgPath = resolve(__dirname, "../package.json"); + +// Parse once; keep raw for snapshot assertions. +const raw = readFileSync(pkgPath, "utf-8"); +const pkg = JSON.parse(raw) as Record; + +// Helper to assert string field value. +function assertField(field: string, expected: string): void { + expect(pkg[field]).toBe(expected); +} + +// Helper to get a nested value. +function nested(obj: Record, ...keys: string[]): T { + let cur: unknown = obj; + for (const k of keys) { + if (typeof cur !== "object" || cur === null) { + throw new Error(`Expected object at key "${k}"`); + } + cur = (cur as Record)[k]; + } + return cur as T; +} + +describe("@ruvnet/rvagent package.json (ADR-124 §2)", () => { + it("§2.1 — name is @ruvnet/rvagent", () => { + assertField("name", "@ruvnet/rvagent"); + }); + + it("§2.2 — version is semver >= 0.1.0", () => { + const version = pkg["version"] as string; + expect(typeof version).toBe("string"); + const [major, minor] = version.split(".").map(Number); + const isAtLeast010 = (major ?? 0) > 0 || (minor ?? 0) >= 1; + expect(isAtLeast010).toBe(true); + }); + + it("§2.3 — engines.node requires Node.js >= 20", () => { + const nodeRange = nested(pkg, "engines", "node"); + expect(typeof nodeRange).toBe("string"); + // Accept >=20 or >=20.0.0 patterns. + expect(nodeRange).toMatch(/>=\s*20/); + }); + + it("§2.4 — bin.rvagent is defined (npx @ruvnet/rvagent invocation)", () => { + const bin = nested>(pkg, "bin"); + expect(typeof bin["rvagent"]).toBe("string"); + expect(bin["rvagent"]).toMatch(/dist\/index\.js/); + }); + + it("§2.5 — exports['.'] has import + types keys (ESM + TypeScript declarations)", () => { + const exports = nested>>(pkg, "exports"); + const dotExport = exports["."]; + expect(dotExport).toBeDefined(); + expect(typeof dotExport?.["import"]).toBe("string"); + expect(typeof dotExport?.["types"]).toBe("string"); + }); + + it("§2.6 — publishConfig.access is 'public' (scoped package requirement)", () => { + const access = nested(pkg, "publishConfig", "access"); + expect(access).toBe("public"); + }); + + it("§2.7 — @modelcontextprotocol/sdk is a runtime dependency", () => { + const deps = nested>(pkg, "dependencies"); + expect(typeof deps["@modelcontextprotocol/sdk"]).toBe("string"); + }); + + it("§2.8 — zod is a runtime dependency", () => { + const deps = nested>(pkg, "dependencies"); + expect(typeof deps["zod"]).toBe("string"); + }); + + it("§2.9 — type is 'module' (ESM-first, Node.js 20+ native)", () => { + assertField("type", "module"); + }); + + it("§2.10 — license is Apache-2.0", () => { + assertField("license", "Apache-2.0"); + }); +});