Skip to content

Commit 5aec1a2

Browse files
committed
chore(release): add publication preflight
Prepare 2.3.4 with generated tool schemas, a line-coverage gate, and clean-tree checks before tagging.
1 parent c751aed commit 5aec1a2

19 files changed

Lines changed: 1206 additions & 93 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,13 @@ jobs:
2828
- name: Lint and format check
2929
run: bun run check
3030

31+
- name: Tool schema snapshot check
32+
run: bun run schema:tools:check
33+
3134
- name: Unit tests with coverage
3235
run: |
3336
bun run test:coverage 2>&1 | tee /tmp/coverage.txt
34-
node -e "
35-
const out = require('fs').readFileSync('/tmp/coverage.txt', 'utf8');
36-
const m = out.match(/all files[^\|]*\|\s*([\d.]+)/i);
37-
if (!m) { console.log('No coverage summary found — skipping threshold check.'); process.exit(0); }
38-
const pct = parseFloat(m[1]);
39-
const min = 80;
40-
if (pct < min) { process.stderr.write('Coverage ' + pct.toFixed(1) + '% is below minimum ' + min + '%\n'); process.exit(1); }
41-
console.log('Coverage OK: ' + pct.toFixed(1) + '%');
42-
"
37+
bun run coverage:check /tmp/coverage.txt 80
4338
4439
- name: Assert Node.js version
4540
run: node -e "const v=+process.version.slice(1).split('.')[0]; if(v<22)process.exit(1)"

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ IDEs injecting this as context: do not re-link from rules.
3636
| [`src/server/git-cherry-pick-tool.ts`](src/server/git-cherry-pick-tool.ts) | `git_cherry_pick` — mutating |
3737
| [`src/server/git-reset-soft-tool.ts`](src/server/git-reset-soft-tool.ts) | `git_reset_soft` — soft-reset; mutating |
3838
| [`src/server/presets-resource.ts`](src/server/presets-resource.ts) | `rethunk-git://presets` resource |
39+
| [`src/server/tool-parameter-schemas.ts`](src/server/tool-parameter-schemas.ts) | `buildToolParameterSchemaDocument`, `captureToolParameterSchemas`; backs `tool-parameters.schema.json` |
3940
| [`src/repo-paths.ts`](src/repo-paths.ts) | `resolvePathForRepo`, `assertRelativePathUnderTop`, `isStrictlyUnderGitTop` |
4041

4142
## Changing contracts
@@ -47,7 +48,7 @@ IDEs injecting this as context: do not re-link from rules.
4748

4849
## Validate + CI
4950

50-
Local: `bun run build` | `bun run check` | `bun run test`. CI ([`ci.yml`](.github/workflows/ci.yml)) runs same on PRs + `main` after `bun install --frozen-lockfile`, uploads prerelease `npm pack` artifact. Tag `v*.*.*` matching `package.json` version → [`release.yml`](.github/workflows/release.yml) publishes to GitHub Packages as `@rethunk-ai/mcp-multi-root-git` + cuts GitHub Release. npmjs publish is manual (see [HUMANS.md](HUMANS.md)).
51+
Local: `bun run build` | `bun run check` | `bun run schema:tools:check` | `bun run test`. CI ([`ci.yml`](.github/workflows/ci.yml)) runs same on PRs + `main` after `bun install --frozen-lockfile`, then `bun run test:coverage` + `bun run coverage:check`, and uploads prerelease `npm pack` artifact. Tag `v*.*.*` matching `package.json` version → [`release.yml`](.github/workflows/release.yml) publishes to GitHub Packages as `@rethunk-ai/mcp-multi-root-git` + cuts GitHub Release. npmjs publish is manual (see [HUMANS.md](HUMANS.md)).
5152

5253
Optional [`.githooks/`](.githooks): `bun run setup-hooks` once per clone. pre-commit=`check`; pre-push=frozen install + build + check + test.
5354

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
All notable changes to `@rethunk/mcp-multi-root-git` are documented here. Format loosely follows [Keep a Changelog](https://keepachangelog.com); the project uses [Semantic Versioning](https://semver.org).
44

5+
## [2.3.4] — 2026-04-26
6+
7+
Publication-prep patch for the `absoluteGitRoots` line.
8+
9+
### Added
10+
11+
- **`tool-parameters.schema.json`** — generated JSON Schema snapshot for every registered tool parameter surface, plus `bun run schema:tools` / `bun run schema:tools:check`.
12+
- **`git_parity` absolute-root regression coverage** — sibling clone batches are now covered directly.
13+
14+
### Fixed
15+
16+
- **CI coverage gate** now checks `% Lines` from Bun's coverage table instead of accidentally reading `% Funcs`.
17+
18+
### Documentation
19+
20+
- **`HUMANS.md`** — added sibling-clone `absoluteGitRoots` examples for `git_status` and `git_parity`.
21+
- **`docs/mcp-tools.md`** — clarified direct `git_push` use for already-committed work and `git_parity` sibling-clone batches.
22+
523
## [2.3.3] — 2026-04-21
624

725
### Added

CONTRIBUTING.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ bun install
1717
bun run build # rimraf dist && tsc → dist/server.js, dist/server/*.js, dist/repo-paths.js
1818
bun run check # Biome lint + format check
1919
bun run check:fix # auto-fix with Biome
20+
bun run schema:tools # regenerate tool-parameters.schema.json
21+
bun run schema:tools:check # verify the generated tool schema is current
22+
bun run publish:preflight # clean-tree release gate before tagging
2023
bun run test # bun test src/
2124
bun run test:coverage # bun test src/ --coverage
25+
bun run coverage:check /tmp/coverage.txt 80 # validate Bun coverage output captured with tee
2226
bun run setup-hooks # one-time per clone: wire .githooks/
2327
```
2428

@@ -62,15 +66,17 @@ One logical unit per commit. Max ~7 files. Split by theme, not by file count.
6266
1. `bun install --frozen-lockfile`
6367
2. `bun run build`
6468
3. `bun run check` (Biome)
65-
4. `bun run test:coverage` + 80% line coverage threshold assertion
66-
5. Prerelease `npm pack` artifact uploaded (90-day retention)
69+
4. `bun run schema:tools:check`
70+
5. `bun run test:coverage` + `bun run coverage:check /tmp/coverage.txt 80`
71+
6. Prerelease `npm pack` artifact uploaded (90-day retention)
6772

6873
Match the CI steps locally before opening a PR.
6974

7075
## Pull request checklist
7176

7277
- [ ] `bun run build` passes.
7378
- [ ] `bun run check` passes (no Biome errors).
79+
- [ ] `bun run schema:tools:check` passes.
7480
- [ ] `bun run test` passes.
7581
- [ ] Any new tool has a corresponding `*.test.ts` file.
7682
- [ ] `docs/mcp-tools.md` updated if the public tool surface changed.

HUMANS.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ With **multiple MCP file roots**, the server picks a root whose git toplevel def
5353

5454
If you installed from **GitHub Packages**, use **`./node_modules/@rethunk-ai/mcp-multi-root-git/git-mcp-presets.schema.json`** in **`$schema`** instead (see [docs/install.md](docs/install.md#github-packages)).
5555

56+
## Tool parameter schema artifact
57+
58+
The package ships **`tool-parameters.schema.json`**, a generated JSON Schema snapshot of every registered tool's parameter schema. Maintainers regenerate it with:
59+
60+
```bash
61+
bun run schema:tools
62+
```
63+
64+
CI and `prepublishOnly` use:
65+
66+
```bash
67+
bun run schema:tools:check
68+
```
69+
70+
This artifact is for inspection, drift checks, and clients that want an offline schema snapshot. Runtime MCP schema discovery remains the source of truth for connected clients.
71+
5672
**Layouts:**
5773

5874
1. **Wrapped (recommended):** `{ "schemaVersion": "1", "presets": { "<name>": { ... } } }`.
@@ -128,6 +144,14 @@ Tag pushes run [`.github/workflows/release.yml`](.github/workflows/release.yml):
128144

129145
Prerequisite: push a **semver git tag** `vX.Y.Z` that **exactly matches** `version` in `package.json` (e.g. `v1.2.3` and `"version": "1.2.3"`).
130146

147+
Before tagging, run the clean-tree preflight from the release commit:
148+
149+
```bash
150+
bun run publish:preflight
151+
```
152+
153+
It verifies the `package.json` version has a matching `CHANGELOG.md` section, generated tool schemas are current, build/check/coverage pass, and `npm pack --dry-run` includes the expected package files.
154+
131155
### npmjs (manual) — maintainers only
132156

133157
npmjs no longer fits an unattended CI publish flow for this org; **do not** rely on automation to [npmjs](https://www.npmjs.com/package/@rethunk/mcp-multi-root-git). To publish the **same** package name consumers already use (**`@rethunk/mcp-multi-root-git`**):

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
}
2424
},
2525
"files": {
26-
"includes": ["src/**/*", "*.json", "*.md"]
26+
"includes": ["src/**/*", "scripts/**/*", "*.json", "*.md", "!tool-parameters.schema.json"]
2727
}
2828
}

bun.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/mcp-tools.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Pass **`format: "json"`** on any tool for structured JSON instead of markdown (d
3232

3333
Tool JSON bodies are minified and contain only the payload — no `rethunkGitMcp` envelope. Current `MCP_JSON_FORMAT_VERSION` is **`"3"`**; server + format version are discoverable via MCP `initialize`. Payload keys (`groups`, `inventories`, `parity`, `roots`) are stable within a given format version. Preset-related responses may include **`presetSchemaVersion`**.
3434

35+
The package also ships **`tool-parameters.schema.json`**, generated from the registered Zod parameter schemas via `bun run schema:tools`. Connected MCP clients should still prefer live schema discovery from `initialize` / tool listing; the artifact is for offline inspection and drift checks.
36+
3537
### v2/v3 field omission (consumer contract)
3638

3739
To keep responses compact, **optional fields are omitted when they would be empty, `null`, or `false`** — they are not emitted as `null`. Consumers must test for *presence*, not compare to `null`.

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rethunk/mcp-multi-root-git",
3-
"version": "2.3.3",
3+
"version": "2.3.4",
44
"description": "MCP stdio server: multi-root git status, inventory, and HEAD parity checks. Generic tools usable by any workspace.",
55
"type": "module",
66
"private": false,
@@ -11,6 +11,7 @@
1111
"files": [
1212
"dist",
1313
"git-mcp-presets.schema.json",
14+
"tool-parameters.schema.json",
1415
"docs/install.md",
1516
"docs/mcp-tools.md",
1617
"AGENTS.md",
@@ -31,9 +32,13 @@
3132
"build": "rimraf dist && tsc",
3233
"check": "biome check .",
3334
"check:fix": "biome check --write .",
35+
"coverage:check": "bun scripts/check-coverage.ts",
36+
"schema:tools": "bun scripts/generate-tool-parameters-schema.ts",
37+
"schema:tools:check": "bun scripts/generate-tool-parameters-schema.ts --check",
38+
"publish:preflight": "bun scripts/publish-preflight.ts",
3439
"test": "bun test src/",
3540
"test:coverage": "bun test src/ --coverage",
36-
"prepublishOnly": "bun run build && bun run check && bun run test",
41+
"prepublishOnly": "bun run schema:tools:check && bun run build && bun run check && bun run test",
3742
"setup-hooks": "git config core.hooksPath .githooks"
3843
},
3944
"keywords": [

scripts/check-coverage.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { readFileSync } from "node:fs";
2+
3+
import { parseAllFilesLineCoverage } from "../src/server/coverage.js";
4+
5+
function main(): void {
6+
const file = process.argv[2];
7+
const min = Number.parseFloat(process.argv[3] ?? "80");
8+
if (!file) {
9+
process.stderr.write("Usage: bun scripts/check-coverage.ts <coverage-output-file> [min]\n");
10+
process.exit(2);
11+
}
12+
13+
const coverage = parseAllFilesLineCoverage(readFileSync(file, "utf8"));
14+
if (coverage == null) {
15+
process.stderr.write("No All files line coverage summary found.\n");
16+
process.exit(1);
17+
}
18+
if (coverage < min) {
19+
process.stderr.write(
20+
`Line coverage ${coverage.toFixed(2)}% is below minimum ${min.toFixed(2)}%\n`,
21+
);
22+
process.exit(1);
23+
}
24+
console.log(`Line coverage OK: ${coverage.toFixed(2)}%`);
25+
}
26+
27+
if (import.meta.main) {
28+
main();
29+
}

0 commit comments

Comments
 (0)