@pulseengine/rivet 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @pulseengine/rivet
2
+
3
+ SDLC traceability, validation, and MCP server for safety-critical systems.
4
+
5
+ Rivet links requirements, features, architecture, decisions, and verification
6
+ evidence across ISO 26262, DO-178C, ASPICE, and STPA. This npm package bundles
7
+ the `rivet` CLI binary (shipped per-platform via `optionalDependencies`) so it
8
+ can be invoked from any Node.js environment — including as a Claude Code MCP
9
+ server.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ # One-shot (no install) — preferred for CI and MCP registration
15
+ npx @pulseengine/rivet --version
16
+
17
+ # Global install
18
+ npm install -g @pulseengine/rivet
19
+ rivet --version
20
+ ```
21
+
22
+ ## Claude Code MCP server
23
+
24
+ ```bash
25
+ claude mcp add rivet npx -y @pulseengine/rivet mcp
26
+ ```
27
+
28
+ ## Supported platforms
29
+
30
+ - `darwin-arm64`, `darwin-x64`
31
+ - `linux-arm64`, `linux-x64`
32
+ - `win32-x64`
33
+
34
+ Binaries are pre-built and published alongside each GitHub release at
35
+ <https://github.com/pulseengine/rivet/releases>.
36
+
37
+ ## License
38
+
39
+ Apache-2.0. See the [repository](https://github.com/pulseengine/rivet) for
40
+ source, documentation, and issues.
package/index.js ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Platform detection and binary-path resolution for @pulseengine/rivet.
4
+ // Chooses the correct platform-specific optional dependency, or falls back
5
+ // to a locally downloaded binary under ./bin (populated by install.js when
6
+ // optionalDependencies fail to resolve — e.g., on an unsupported platform
7
+ // triplet or with --no-optional).
8
+
9
+ const os = require("os");
10
+ const path = require("path");
11
+
12
+ /**
13
+ * Map (process.platform, process.arch) to the matching @pulseengine platform
14
+ * package name. Throws for unsupported combinations so the caller can surface
15
+ * a clear error.
16
+ */
17
+ function getPlatformPackageName() {
18
+ const platform = os.platform();
19
+ const arch = os.arch();
20
+
21
+ let platformName;
22
+ switch (platform) {
23
+ case "darwin":
24
+ platformName = "darwin";
25
+ break;
26
+ case "linux":
27
+ platformName = "linux";
28
+ break;
29
+ case "win32":
30
+ platformName = "win32";
31
+ break;
32
+ default:
33
+ throw new Error(`Unsupported platform: ${platform}`);
34
+ }
35
+
36
+ let archName;
37
+ switch (arch) {
38
+ case "x64":
39
+ archName = "x64";
40
+ break;
41
+ case "arm64":
42
+ archName = "arm64";
43
+ break;
44
+ default:
45
+ throw new Error(`Unsupported architecture: ${arch}`);
46
+ }
47
+
48
+ return `@pulseengine/rivet-${platformName}-${archName}`;
49
+ }
50
+
51
+ /**
52
+ * Resolve the absolute path to the rivet binary for the current platform.
53
+ * Prefers the optional-dependency platform package; falls back to ./bin
54
+ * (populated by install.js downloading from the GitHub Release).
55
+ */
56
+ function getBinaryPath() {
57
+ const platform = os.platform();
58
+ const binaryName = platform === "win32" ? "rivet.exe" : "rivet";
59
+
60
+ try {
61
+ const platformPackage = getPlatformPackageName();
62
+ const platformPackagePath = require.resolve(`${platformPackage}/package.json`);
63
+ const platformPackageDir = path.dirname(platformPackagePath);
64
+ return path.join(platformPackageDir, binaryName);
65
+ } catch (_err) {
66
+ // Fallback: binary downloaded directly from GitHub release by install.js.
67
+ return path.join(__dirname, "bin", binaryName);
68
+ }
69
+ }
70
+
71
+ function getPlatformInfo() {
72
+ return {
73
+ platform: os.platform(),
74
+ arch: os.arch(),
75
+ platformPackage: getPlatformPackageName(),
76
+ binaryPath: getBinaryPath(),
77
+ binaryName: os.platform() === "win32" ? "rivet.exe" : "rivet",
78
+ };
79
+ }
80
+
81
+ module.exports = {
82
+ getPlatformPackageName,
83
+ getBinaryPath,
84
+ getPlatformInfo,
85
+ };
86
+
87
+ // When invoked directly, print platform info (useful for debugging installs).
88
+ if (require.main === module) {
89
+ try {
90
+ const info = getPlatformInfo();
91
+ console.log("Platform Information:");
92
+ console.log(` Platform: ${info.platform}`);
93
+ console.log(` Architecture: ${info.arch}`);
94
+ console.log(` Platform Package: ${info.platformPackage}`);
95
+ console.log(` Binary Name: ${info.binaryName}`);
96
+ console.log(` Binary Path: ${info.binaryPath}`);
97
+ } catch (err) {
98
+ console.error("Error:", err.message);
99
+ process.exit(1);
100
+ }
101
+ }
package/install.js ADDED
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Post-install hook for @pulseengine/rivet.
4
+ //
5
+ // Preferred path: the platform-specific optional dependency
6
+ // (@pulseengine/rivet-<platform>-<arch>) is already resolved and ships its
7
+ // own pre-built binary — nothing to do.
8
+ //
9
+ // Fallback path: optionalDependencies were skipped (e.g., --no-optional,
10
+ // unusual platform triplet, or npm bug) — download the matching archive
11
+ // from the GitHub Release and extract the binary into ./bin so run.js can
12
+ // find it.
13
+
14
+ const os = require("os");
15
+ const path = require("path");
16
+ const fs = require("fs");
17
+ const https = require("https");
18
+ const { execFileSync } = require("child_process");
19
+
20
+ const { getPlatformPackageName } = require("./index.js");
21
+
22
+ // Fast path: platform package resolved => nothing to do.
23
+ try {
24
+ const platformPackage = getPlatformPackageName();
25
+ try {
26
+ require.resolve(`${platformPackage}/package.json`);
27
+ console.log(`Platform package ${platformPackage} is available, skipping binary download.`);
28
+ process.exit(0);
29
+ } catch (_err) {
30
+ console.log(
31
+ `Platform package ${platformPackage} not found, falling back to GitHub release download.`,
32
+ );
33
+ }
34
+ } catch (_err) {
35
+ console.log(
36
+ "Platform not supported by platform packages, attempting GitHub release download.",
37
+ );
38
+ }
39
+
40
+ // --- Fallback: download from GitHub release ---------------------------------
41
+
42
+ function getRustTarget() {
43
+ const type = os.type();
44
+ const arch = os.arch();
45
+
46
+ let platform;
47
+ if (type === "Windows_NT") platform = "pc-windows-msvc";
48
+ else if (type === "Linux") platform = "unknown-linux-gnu";
49
+ else if (type === "Darwin") platform = "apple-darwin";
50
+ else throw new Error(`Unsupported OS: ${type}`);
51
+
52
+ let archSuffix;
53
+ if (arch === "x64") archSuffix = "x86_64";
54
+ else if (arch === "arm64") archSuffix = "aarch64";
55
+ else throw new Error(`Unsupported architecture: ${arch}`);
56
+
57
+ return `${archSuffix}-${platform}`;
58
+ }
59
+
60
+ function getBinaryName() {
61
+ return os.type() === "Windows_NT" ? "rivet.exe" : "rivet";
62
+ }
63
+
64
+ function getDownloadUrl() {
65
+ const version = require("./package.json").version;
66
+ const target = getRustTarget();
67
+ const ext = os.type() === "Windows_NT" ? "zip" : "tar.gz";
68
+ // release.yml uploads archives named: rivet-v<version>-<target>.<ext>
69
+ return `https://github.com/pulseengine/rivet/releases/download/v${version}/rivet-v${version}-${target}.${ext}`;
70
+ }
71
+
72
+ function downloadFile(url, destination) {
73
+ return new Promise((resolve, reject) => {
74
+ const file = fs.createWriteStream(destination);
75
+
76
+ https
77
+ .get(url, (response) => {
78
+ if (response.statusCode === 301 || response.statusCode === 302) {
79
+ file.close();
80
+ fs.unlink(destination, () => {});
81
+ return downloadFile(response.headers.location, destination)
82
+ .then(resolve)
83
+ .catch(reject);
84
+ }
85
+ if (response.statusCode !== 200) {
86
+ file.close();
87
+ fs.unlink(destination, () => {});
88
+ return reject(
89
+ new Error(`HTTP ${response.statusCode}: ${response.statusMessage} (${url})`),
90
+ );
91
+ }
92
+
93
+ response.pipe(file);
94
+ file.on("finish", () => {
95
+ file.close();
96
+ resolve();
97
+ });
98
+ file.on("error", (err) => {
99
+ fs.unlink(destination, () => {});
100
+ reject(err);
101
+ });
102
+ })
103
+ .on("error", (err) => {
104
+ fs.unlink(destination, () => {});
105
+ reject(err);
106
+ });
107
+ });
108
+ }
109
+
110
+ // Extract via execFile (no shell) to avoid any injection surface. Inputs are
111
+ // already hardcoded paths we just constructed, but the argv form is the
112
+ // correct idiom regardless.
113
+ function extractArchive(archivePath, destDir) {
114
+ if (os.type() === "Windows_NT") {
115
+ execFileSync(
116
+ "powershell",
117
+ [
118
+ "-NoProfile",
119
+ "-Command",
120
+ `Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force`,
121
+ ],
122
+ { stdio: "inherit" },
123
+ );
124
+ } else {
125
+ execFileSync("tar", ["-xzf", archivePath, "-C", destDir], { stdio: "inherit" });
126
+ }
127
+ }
128
+
129
+ async function installBinary() {
130
+ const binaryName = getBinaryName();
131
+ const url = getDownloadUrl();
132
+ const target = getRustTarget();
133
+
134
+ console.log(`Platform: ${os.type()} ${os.arch()}`);
135
+ console.log(`Target: ${target}`);
136
+ console.log(`Binary: ${binaryName}`);
137
+ console.log(`URL: ${url}`);
138
+
139
+ const binDir = path.join(__dirname, "bin");
140
+ if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true });
141
+
142
+ const ext = os.type() === "Windows_NT" ? "zip" : "tar.gz";
143
+ const archivePath = path.join(binDir, `rivet.${ext}`);
144
+
145
+ console.log("Downloading binary...");
146
+ await downloadFile(url, archivePath);
147
+
148
+ console.log("Extracting...");
149
+ extractArchive(archivePath, binDir);
150
+
151
+ fs.unlinkSync(archivePath);
152
+
153
+ if (os.type() !== "Windows_NT") {
154
+ const binaryPath = path.join(binDir, binaryName);
155
+ if (fs.existsSync(binaryPath)) fs.chmodSync(binaryPath, 0o755);
156
+ }
157
+
158
+ console.log("rivet binary installed.");
159
+ }
160
+
161
+ installBinary().catch((err) => {
162
+ console.error("Failed to install rivet binary:", err.message);
163
+ console.error("");
164
+ console.error("You can:");
165
+ console.error(" 1. Install from source:");
166
+ console.error(
167
+ " cargo install --git https://github.com/pulseengine/rivet.git rivet-cli",
168
+ );
169
+ console.error(" 2. Download a release manually:");
170
+ console.error(" https://github.com/pulseengine/rivet/releases");
171
+ // Do not fail the install: optionalDependencies are the primary path and a
172
+ // hard failure here would make `npm install` fail on platforms where the
173
+ // platform package was actually resolved (npm runs postinstall regardless).
174
+ process.exit(0);
175
+ });
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@pulseengine/rivet",
3
+ "version": "0.7.0",
4
+ "description": "Rivet — SDLC traceability, validation, and MCP server for safety-critical systems (ISO 26262, DO-178C, ASPICE, STPA)",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "rivet": "./run.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node install.js",
11
+ "preuninstall": "node uninstall.js"
12
+ },
13
+ "keywords": [
14
+ "mcp",
15
+ "model-context-protocol",
16
+ "sdlc",
17
+ "traceability",
18
+ "safety",
19
+ "iso-26262",
20
+ "do-178c",
21
+ "aspice",
22
+ "stpa",
23
+ "requirements",
24
+ "verification",
25
+ "rust",
26
+ "cli"
27
+ ],
28
+ "author": "PulseEngine <https://github.com/pulseengine>",
29
+ "license": "Apache-2.0",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/pulseengine/rivet.git"
33
+ },
34
+ "homepage": "https://github.com/pulseengine/rivet#readme",
35
+ "bugs": {
36
+ "url": "https://github.com/pulseengine/rivet/issues"
37
+ },
38
+ "optionalDependencies": {
39
+ "@pulseengine/rivet-darwin-arm64": "0.7.0",
40
+ "@pulseengine/rivet-darwin-x64": "0.7.0",
41
+ "@pulseengine/rivet-linux-arm64": "0.7.0",
42
+ "@pulseengine/rivet-linux-x64": "0.7.0",
43
+ "@pulseengine/rivet-win32-x64": "0.7.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=14"
47
+ },
48
+ "os": [
49
+ "darwin",
50
+ "linux",
51
+ "win32"
52
+ ],
53
+ "cpu": [
54
+ "x64",
55
+ "arm64"
56
+ ],
57
+ "files": [
58
+ "index.js",
59
+ "install.js",
60
+ "run.js",
61
+ "uninstall.js",
62
+ "README.md"
63
+ ],
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }
package/run.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Thin wrapper that spawns the rivet binary resolved via ./index.js.
4
+ // Forwards argv, stdio, and exit code; propagates signals to the child.
5
+
6
+ const { spawn } = require("child_process");
7
+ const fs = require("fs");
8
+ const { getBinaryPath } = require("./index.js");
9
+
10
+ function runRivet() {
11
+ let binaryPath;
12
+ try {
13
+ binaryPath = getBinaryPath();
14
+ } catch (err) {
15
+ console.error("Error resolving rivet binary:", err.message);
16
+ console.error("");
17
+ console.error("Your platform may not be supported. Supported targets:");
18
+ console.error(" - darwin-arm64, darwin-x64");
19
+ console.error(" - linux-arm64, linux-x64");
20
+ console.error(" - win32-x64");
21
+ console.error("");
22
+ console.error(
23
+ "Install from source: cargo install --git https://github.com/pulseengine/rivet.git rivet-cli",
24
+ );
25
+ process.exit(1);
26
+ }
27
+
28
+ if (!fs.existsSync(binaryPath)) {
29
+ console.error("rivet binary not found at:", binaryPath);
30
+ console.error("");
31
+ console.error("This usually means:");
32
+ console.error(" 1. optionalDependencies failed to install for your platform");
33
+ console.error(" 2. The GitHub release fallback download failed");
34
+ console.error(" 3. Your platform is not supported");
35
+ console.error("");
36
+ console.error("Try: npm install --force @pulseengine/rivet");
37
+ console.error(
38
+ "Or install from source: cargo install --git https://github.com/pulseengine/rivet.git rivet-cli",
39
+ );
40
+ process.exit(1);
41
+ }
42
+
43
+ const child = spawn(binaryPath, process.argv.slice(2), {
44
+ stdio: "inherit",
45
+ env: process.env,
46
+ });
47
+
48
+ child.on("error", (err) => {
49
+ console.error("Failed to start rivet:", err.message);
50
+ process.exit(1);
51
+ });
52
+
53
+ child.on("exit", (code, signal) => {
54
+ if (signal) {
55
+ process.kill(process.pid, signal);
56
+ } else {
57
+ process.exit(code == null ? 0 : code);
58
+ }
59
+ });
60
+
61
+ process.on("SIGINT", () => child.kill("SIGINT"));
62
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
63
+ }
64
+
65
+ runRivet();
package/uninstall.js ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Pre-uninstall hook: remove binaries downloaded into ./bin by install.js.
4
+ // Platform packages (optional deps) clean themselves up via normal npm
5
+ // lifecycle — no action needed for those.
6
+
7
+ const fs = require("fs");
8
+ const path = require("path");
9
+
10
+ const binDir = path.join(__dirname, "bin");
11
+
12
+ if (fs.existsSync(binDir)) {
13
+ try {
14
+ fs.rmSync(binDir, { recursive: true, force: true });
15
+ } catch (err) {
16
+ console.error("Failed to clean rivet bin/:", err.message);
17
+ }
18
+ }