@createsomething/ground-mcp 0.3.2 → 0.3.3

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 CHANGED
@@ -48,27 +48,39 @@ safe to run from a package inside a monorepo.
48
48
 
49
49
  ### Diff coverage
50
50
 
51
- `ground diff` determines analyzability from the requested checks. Its current
52
- duplicate and orphan checks cover TypeScript, JavaScript, and `.mjs` source
53
- paths. The legacy `changed_files` and `changed_file_list` fields continue to
54
- describe only analyzable source files. Use the added
55
- `discovered_changed_files`, `analyzable_changed_files`, and
56
- `excluded_changed_files` fields to see the full Git change scope and why a path
57
- was not analyzed, including `unsupported_by_requested_checks`. If no changed
58
- source is eligible, the result explicitly says so; it does not describe
59
- excluded files as clean.
60
-
61
- For promotion evidence, inspect `check_coverage.<check>.status`,
62
- `analyzed_changed_files`, and `excluded_changed_files`. Ground 0.3.2 removes
63
- `ground diff`'s silent 500-file truncation and makes source traversal
64
- deterministic and cycle-safe. Diff mode parses the complete corpus but only
65
- compares pairs involving changed files. A changed file is only listed as
66
- analyzed for a check after that check completed for the file; partial or failed
67
- analysis stays explicit in the per-check exclusions. Standalone broad duplicate
68
- scans retain their safety bound and report `scan_complete: false` when it is hit.
69
-
70
- The release package includes the native Apple Silicon binaries directly; other
71
- supported platforms download the matching verified release asset during install.
51
+ Every batch, diff, and duplicate-function response has a
52
+ `verification_status`; `ground diff` also returns the same status per requested
53
+ check in `check_coverage.<check>.status`. The contract is explicit:
54
+
55
+ - `PASS`: the check completed for the relevant supported files and found no issue.
56
+ - `FAIL`: the check found an issue or could not complete because of a read/parse failure.
57
+ - `NOT_APPLICABLE`: no changed file needs that check.
58
+ - `UNSUPPORTED`: relevant source exists, but the requested check cannot analyze its language (including Svelte duplicate-function scans).
59
+ - `TIMEOUT`: duplicate analysis reached its deadline before a complete result was available.
60
+
61
+ `ground analyze` and `ground diff` accept `--timeout-ms` (120000 by default).
62
+ The MCP equivalents accept `timeout_ms`; a deadline returns `TIMEOUT`, never a
63
+ clean result. `ground diff` includes `.mjs` with JavaScript source analysis.
64
+ Its `changed_files` and `changed_file_list` fields remain the analyzable-file
65
+ view; read `discovered_changed_files`, `analyzable_changed_files`, and
66
+ `excluded_changed_files` for the full Git scope. Per-check coverage also names
67
+ `unsupported_changed_files` and `excluded_changed_files`, so a clean claim is
68
+ valid only with `PASS`.
69
+
70
+ Ground 0.3.3 keeps `ground diff`'s complete changed-file coverage and makes
71
+ source traversal deterministic and cycle-safe. Diff mode parses the complete
72
+ corpus but only compares pairs involving changed files. Standalone broad
73
+ duplicate scans retain their safety bound and report their non-pass status with
74
+ `scan_complete: false` when the bound is hit.
75
+
76
+ The release package ships thin command wrappers for every platform. Install
77
+ downloads the matching versioned release asset and verifies its SHA-256 against
78
+ that release's `SHA256SUMS` manifest before extracting it. Record the artifact
79
+ that produced a receipt with:
80
+
81
+ ```bash
82
+ ground build-info --json
83
+ ```
72
84
 
73
85
  ## The Problem
74
86
 
@@ -217,7 +229,7 @@ The npm package downloads a platform-specific binary on install. If that failed:
217
229
 
218
230
  ```bash
219
231
  # Check if the binary exists
220
- ls node_modules/@createsomething/ground-mcp/bin/
232
+ ls node_modules/@createsomething/ground-mcp/bin/native/
221
233
 
222
234
  # Re-install
223
235
  npm install @createsomething/ground-mcp
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('./run-native').runNative('ground-mcp');
package/bin/ground.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('./run-native').runNative('ground');
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,27 @@
1
+ const { spawnSync } = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ function runNative(binaryName) {
6
+ const extension = process.platform === 'win32' ? '.exe' : '';
7
+ const binary = path.join(__dirname, 'native', `${binaryName}${extension}`);
8
+
9
+ if (!fs.existsSync(binary)) {
10
+ console.error(
11
+ `Ground MCP native binary is unavailable at ${binary}. Reinstall @createsomething/ground-mcp to complete the verified release-asset download.`
12
+ );
13
+ process.exitCode = 1;
14
+ return;
15
+ }
16
+
17
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' });
18
+ if (result.error) {
19
+ console.error(`Ground MCP could not start ${binaryName}: ${result.error.message}`);
20
+ process.exitCode = 1;
21
+ return;
22
+ }
23
+
24
+ process.exitCode = result.status ?? 1;
25
+ }
26
+
27
+ module.exports = { runNative };
package/install.js CHANGED
@@ -7,10 +7,10 @@
7
7
  */
8
8
 
9
9
  const { execSync } = require('child_process');
10
+ const { createHash } = require('crypto');
10
11
  const fs = require('fs');
11
12
  const https = require('https');
12
13
  const path = require('path');
13
- const zlib = require('zlib');
14
14
 
15
15
  const REPO = 'createsomethingtoday/create-something-monorepo';
16
16
  const VERSION = require('./package.json').version;
@@ -51,20 +51,24 @@ function getDownloadUrl(binaryName, platform = process.platform) {
51
51
  return `https://github.com/${REPO}/releases/download/ground-v${VERSION}/ground-${binaryName}.${ext}`;
52
52
  }
53
53
 
54
- function hasBundledNativeBinaries() {
55
- // The npm artifact includes a release-built Apple Silicon bootstrap pair.
56
- // Other platforms continue through the release-asset downloader below.
57
- if (getPlatformKey() !== 'darwin-arm64') return false;
58
-
59
- const binDir = path.join(__dirname, 'bin');
60
- return ['ground', 'ground-mcp'].every((name) => {
61
- const binary = path.join(binDir, name);
62
- try {
63
- return fs.statSync(binary).isFile() && (fs.statSync(binary).mode & 0o111) !== 0;
64
- } catch {
65
- return false;
66
- }
67
- });
54
+ function getChecksumsUrl() {
55
+ return `https://github.com/${REPO}/releases/download/ground-v${VERSION}/SHA256SUMS`;
56
+ }
57
+
58
+ function verifyArchiveIntegrity(archive, assetName, checksums) {
59
+ const expected = checksums
60
+ .split(/\r?\n/)
61
+ .map((line) => line.trim().match(/^([a-f0-9]{64})\s+\*?(.+)$/i))
62
+ .find((match) => match?.[2] === assetName)?.[1];
63
+
64
+ if (!expected) {
65
+ throw new Error(`Release checksum manifest does not contain a checksum for ${assetName}`);
66
+ }
67
+
68
+ const actual = createHash('sha256').update(archive).digest('hex');
69
+ if (actual !== expected.toLowerCase()) {
70
+ throw new Error(`Release checksum mismatch for ${assetName}`);
71
+ }
68
72
  }
69
73
 
70
74
  async function download(url) {
@@ -119,16 +123,11 @@ async function install() {
119
123
  return;
120
124
  }
121
125
 
122
- if (hasBundledNativeBinaries()) {
123
- console.log('Ground MCP: Using bundled darwin-arm64 binaries');
124
- return;
125
- }
126
-
127
126
  console.log('Ground MCP: Installing binary...');
128
127
 
129
128
  const binaryName = getBinaryName();
130
129
  const url = getDownloadUrl(binaryName);
131
- const binDir = path.join(__dirname, 'bin');
130
+ const binDir = path.join(__dirname, 'bin', 'native');
132
131
 
133
132
  console.log(`Platform: ${getPlatformKey()}`);
134
133
  console.log(`Downloading: ${url}`);
@@ -141,6 +140,8 @@ async function install() {
141
140
 
142
141
  // Download archive
143
142
  const buffer = await download(url);
143
+ const checksums = await download(getChecksumsUrl());
144
+ verifyArchiveIntegrity(buffer, path.basename(url), checksums.toString('utf8'));
144
145
  console.log(`Downloaded ${(buffer.length / 1024 / 1024).toFixed(2)} MB`);
145
146
 
146
147
  // Extract based on platform
@@ -203,5 +204,8 @@ if (require.main === module) {
203
204
  }
204
205
 
205
206
  module.exports = {
207
+ download,
206
208
  getDownloadUrl,
209
+ getChecksumsUrl,
210
+ verifyArchiveIntegrity,
207
211
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@createsomething/ground-mcp",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Grounded claims for code. MCP server that prevents AI hallucination in code analysis.",
5
5
  "author": "CREATE SOMETHING <hello@createsomething.io>",
6
6
  "license": "MIT",
@@ -48,11 +48,12 @@
48
48
  "css-analysis"
49
49
  ],
50
50
  "bin": {
51
- "ground": "bin/ground",
52
- "ground-mcp": "bin/ground-mcp"
51
+ "ground": "bin/ground.js",
52
+ "ground-mcp": "bin/ground-mcp.js"
53
53
  },
54
54
  "scripts": {
55
55
  "postinstall": "node install.js",
56
+ "prepublishOnly": "node release-verify.js",
56
57
  "pilot:build": "cargo build --release --manifest-path ../Cargo.toml --bin ground --bin ground-mcp",
57
58
  "pilot:benchmark": "tsx pilot/benchmark.ts",
58
59
  "pilot:check": "tsc --noEmit -p pilot/tsconfig.json",
package/bin/.gitkeep DELETED
@@ -1,4 +0,0 @@
1
- # Binary files are downloaded during npm install
2
- # This directory will contain:
3
- # - ground-mcp (or ground-mcp.exe on Windows)
4
- # - ground (or ground.exe on Windows)
package/bin/ground DELETED
Binary file
package/bin/ground-mcp DELETED
Binary file