@zereight/mcp-gitlab 2.1.70 → 2.2.1
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.ko.md +9 -5
- package/README.md +15 -11
- package/README.pt-BR.md +9 -5
- package/README.zh-CN.md +9 -5
- package/build/config.js +12 -4
- package/build/deprecated-env.js +63 -0
- package/build/index.js +430 -200
- package/build/oauth-device-flow.js +80 -0
- package/build/oauth.js +135 -18
- package/build/schemas.js +1 -1
- package/build/server/remote-http-stack.js +39 -0
- package/build/tools/discover-activation.js +38 -0
- package/build/tools/exposed-tools.js +35 -0
- package/build/tools/listed-tools.js +76 -0
- package/build/tools/registry.js +232 -63
- package/build/tools/tool-descriptions.js +3 -3
- package/build/tools/tool-profile.js +66 -0
- package/build/utils/compact-tool-allowlist.js +14 -0
- package/build/utils/logger.js +34 -12
- package/package.json +3 -3
- package/build/scripts/check-skill-sync.js +0 -143
- package/build/scripts/generate-server-card.js +0 -39
- package/build/scripts/generate-tool-coverage.js +0 -58
- package/build/scripts/generate-tool-docs.js +0 -430
- package/build/scripts/tool-coverage/coverage.js +0 -341
- package/build/scripts/tool-coverage/coverage.test.js +0 -142
- package/build/test/callback-proxy-tests.js +0 -321
- package/build/test/cli/args.test.js +0 -175
- package/build/test/cli/boolean-flags.test.js +0 -106
- package/build/test/cli/compact-mcp-result.test.js +0 -93
- package/build/test/cli/credentials.test.js +0 -153
- package/build/test/cli/exposure.test.js +0 -104
- package/build/test/cli/load-config-snapshot.js +0 -5
- package/build/test/cli/output.test.js +0 -74
- package/build/test/cli/replay-command.test.js +0 -37
- package/build/test/cli/router.test.js +0 -183
- package/build/test/client-pool-test.js +0 -109
- package/build/test/clients/client.js +0 -34
- package/build/test/clients/custom-header-client.js +0 -122
- package/build/test/clients/sse-client.js +0 -95
- package/build/test/clients/stdio-client.js +0 -113
- package/build/test/clients/streamable-http-client.js +0 -95
- package/build/test/config-allowed-groups.test.js +0 -97
- package/build/test/create-commit-actions.test.js +0 -102
- package/build/test/draft-note-schema.test.js +0 -44
- package/build/test/dynamic-api-url-allowlist.test.js +0 -121
- package/build/test/dynamic-api-url-test.js +0 -304
- package/build/test/dynamic-routing-tests.js +0 -495
- package/build/test/get-merge-request-discussion-schema.test.js +0 -30
- package/build/test/gitlab-api-tool-errors.test.js +0 -112
- package/build/test/gitlab-artifact-entry-schema.test.js +0 -44
- package/build/test/gitlab-diff-schema.test.js +0 -36
- package/build/test/gitlab-pipeline-schedule-schema.test.js +0 -32
- package/build/test/gitlab-tag-schema.test.js +0 -51
- package/build/test/group-milestone-schema.test.js +0 -45
- package/build/test/mcp-oauth-tests.js +0 -905
- package/build/test/mcp-server-name.test.js +0 -87
- package/build/test/merge-merge-request-schema.test.js +0 -75
- package/build/test/multi-server-test.js +0 -190
- package/build/test/no-proxy-integration-test.js +0 -183
- package/build/test/no-proxy-test.js +0 -149
- package/build/test/nullable-gitlab-response-fields.test.js +0 -37
- package/build/test/nullish-tool-arguments-schema.test.js +0 -118
- package/build/test/oauth-device-flow-tests.js +0 -450
- package/build/test/oauth-download-url.test.js +0 -157
- package/build/test/oauth-startup.test.js +0 -204
- package/build/test/oauth-tests.js +0 -428
- package/build/test/path-segment-encoding.test.js +0 -98
- package/build/test/remote-auth-simple-test.js +0 -277
- package/build/test/remote-auth-tests.js +0 -314
- package/build/test/response-masking.test.js +0 -445
- package/build/test/schema-tests.js +0 -1679
- package/build/test/server/metrics.test.js +0 -47
- package/build/test/server/request-helpers.test.js +0 -48
- package/build/test/server/version.test.js +0 -13
- package/build/test/sse-auth-guard.test.js +0 -96
- package/build/test/sse-session-limits.test.js +0 -273
- package/build/test/stateless/callback-proxy.test.js +0 -510
- package/build/test/stateless/client-id.test.js +0 -177
- package/build/test/stateless/codec.test.js +0 -328
- package/build/test/stateless/config-ttl.test.js +0 -149
- package/build/test/stateless/consumed-proxy-code-cache.test.js +0 -150
- package/build/test/stateless/session-id-integration.test.js +0 -675
- package/build/test/stateless/session-id.test.js +0 -157
- package/build/test/streamable-http-concurrent-session.test.js +0 -171
- package/build/test/streamable-http-dns-rebinding.test.js +0 -185
- package/build/test/streamable-http-sse-stream.test.js +0 -350
- package/build/test/streamable-http-static-token-auth.test.js +0 -157
- package/build/test/streamable-http-unauthenticated-discovery.test.js +0 -207
- package/build/test/test-all-transport-server.js +0 -255
- package/build/test/test-auth-retry.js +0 -195
- package/build/test/test-blank-filters.js +0 -156
- package/build/test/test-ci-catalog.js +0 -177
- package/build/test/test-ci-lint.js +0 -191
- package/build/test/test-ci-variables.js +0 -309
- package/build/test/test-create-repository.js +0 -120
- package/build/test/test-dependency-proxy.js +0 -195
- package/build/test/test-deployment-tools.js +0 -463
- package/build/test/test-download-attachment.js +0 -190
- package/build/test/test-dynamic-project-scope.js +0 -524
- package/build/test/test-empty-toolsets.js +0 -535
- package/build/test/test-get-file-blame.js +0 -145
- package/build/test/test-get-file-contents.js +0 -128
- package/build/test/test-geteffectiveprojectid.js +0 -804
- package/build/test/test-health-check.js +0 -115
- package/build/test/test-issue-description-patch.js +0 -256
- package/build/test/test-job-artifacts.js +0 -275
- package/build/test/test-json-schema.js +0 -166
- package/build/test/test-list-group-members.js +0 -150
- package/build/test/test-list-group-merge-requests.js +0 -165
- package/build/test/test-list-issues.js +0 -170
- package/build/test/test-list-merge-requests.js +0 -201
- package/build/test/test-list-milestones.js +0 -145
- package/build/test/test-list-project-members.js +0 -132
- package/build/test/test-merge-request-approval-state-tools.js +0 -213
- package/build/test/test-merge-request-approvals.js +0 -187
- package/build/test/test-merge-request-pipelines.js +0 -106
- package/build/test/test-mr-diffs-filter.js +0 -132
- package/build/test/test-mr-file-diffs.js +0 -251
- package/build/test/test-oauth-proxy-rate-limit.js +0 -133
- package/build/test/test-orbit.js +0 -155
- package/build/test/test-permission-mode.js +0 -424
- package/build/test/test-pipeline-schedules.js +0 -484
- package/build/test/test-protected-branches.js +0 -174
- package/build/test/test-remote-downloads.js +0 -510
- package/build/test/test-search-code.js +0 -275
- package/build/test/test-snippets.js +0 -735
- package/build/test/test-tags.js +0 -220
- package/build/test/test-todos.js +0 -195
- package/build/test/test-token-optimizations.js +0 -691
- package/build/test/test-toolset-filtering.js +0 -499
- package/build/test/test-update-issue-slim.js +0 -141
- package/build/test/test-update-project.js +0 -112
- package/build/test/test-upload-markdown.js +0 -206
- package/build/test/test-vulnerabilities.js +0 -399
- package/build/test/test-webhooks.js +0 -218
- package/build/test/tool-description-quality.test.js +0 -50
- package/build/test/utils/bulk-publish-options.test.js +0 -32
- package/build/test/utils/download-token.test.js +0 -35
- package/build/test/utils/forwarded-public-base-url.test.js +0 -46
- package/build/test/utils/gitlab-instance-version.test.js +0 -32
- package/build/test/utils/gitlab-version-gate.test.js +0 -74
- package/build/test/utils/graphql-query.test.js +0 -168
- package/build/test/utils/helpers-path.test.js +0 -104
- package/build/test/utils/jmespath-tool-result.test.js +0 -91
- package/build/test/utils/masking.test.js +0 -384
- package/build/test/utils/merge-request-position.test.js +0 -57
- package/build/test/utils/mock-gitlab-server.js +0 -614
- package/build/test/utils/proxy-client-ip.test.js +0 -28
- package/build/test/utils/redact-sensitive.test.js +0 -32
- package/build/test/utils/safe-redirect-fetch.test.js +0 -463
- package/build/test/utils/server-launcher.js +0 -231
- package/build/test/utils/tool-args.test.js +0 -210
- package/build/test/utils/url.test.js +0 -141
- package/build/test/utils/version-check.test.js +0 -239
- package/build/test/utils/wiki-title.test.js +0 -21
- package/build/test-note.js +0 -54
- package/build/test-resolve-issue-note.js +0 -127
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zereight/mcp-gitlab",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"mcpName": "io.github.zereight/gitlab-mcp",
|
|
5
5
|
"description": "GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more",
|
|
6
6
|
"keywords": [
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"npm": ">=9.0.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
|
-
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
|
|
47
|
+
"build": "node -e \"require('fs').rmSync('build',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
|
|
48
48
|
"prepare": "npm run build",
|
|
49
49
|
"dev": "npm run build && node build/index.js",
|
|
50
|
-
"watch": "tsc --watch",
|
|
50
|
+
"watch": "tsc -p tsconfig.build.json --watch",
|
|
51
51
|
"deploy": "npm publish --access public",
|
|
52
52
|
"changelog": "auto-changelog -p",
|
|
53
53
|
"test": "npm run test:all",
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
/**
|
|
3
|
-
* Verify skills/gitlab-mcp/ stays in sync with tools/registry.ts.
|
|
4
|
-
*
|
|
5
|
-
* Run with: npm run check:skill-sync
|
|
6
|
-
*/
|
|
7
|
-
import { readFileSync, readdirSync } from "node:fs";
|
|
8
|
-
import { dirname, join } from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { TOOLSET_DEFINITIONS, allTools, destructiveTools, DEFAULT_TOOLSET_IDS, } from "../tools/registry.js";
|
|
11
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
const REPO_ROOT = join(__dirname, "..");
|
|
13
|
-
const SKILL_PATH = join(REPO_ROOT, "skills", "gitlab-mcp", "SKILL.md");
|
|
14
|
-
const REF_DIR = join(REPO_ROOT, "skills", "gitlab-mcp", "reference");
|
|
15
|
-
// Response field names in reference docs — not MCP tools.
|
|
16
|
-
const REFERENCE_FIELD_ALLOWLIST = new Set([
|
|
17
|
-
"after",
|
|
18
|
-
"allow_multiple",
|
|
19
|
-
"deleted_file",
|
|
20
|
-
"excluded_file_patterns",
|
|
21
|
-
"group_id",
|
|
22
|
-
"new_file",
|
|
23
|
-
"new_path",
|
|
24
|
-
"old_path",
|
|
25
|
-
"name",
|
|
26
|
-
"page",
|
|
27
|
-
"per_page",
|
|
28
|
-
"pipeline_id",
|
|
29
|
-
"job_inputs",
|
|
30
|
-
"project_id",
|
|
31
|
-
"renamed_file",
|
|
32
|
-
]);
|
|
33
|
-
function fail(message) {
|
|
34
|
-
console.error(`::error::${message}`);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
function parseToolsetTable(skill) {
|
|
38
|
-
const rows = new Map();
|
|
39
|
-
const rowRe = /^\| ([a-z_]+) \((\d+) tools?\) \| (yes|no) \|/gm;
|
|
40
|
-
let match;
|
|
41
|
-
while ((match = rowRe.exec(skill)) !== null) {
|
|
42
|
-
rows.set(match[1], {
|
|
43
|
-
count: Number(match[2]),
|
|
44
|
-
isDefault: match[3] === "yes",
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return rows;
|
|
48
|
-
}
|
|
49
|
-
function parseIntroCounts(skill) {
|
|
50
|
-
const match = skill.match(/providing (\d+) tools: (\d+) tools across (\d+) toolsets/);
|
|
51
|
-
if (!match) {
|
|
52
|
-
fail("skills/gitlab-mcp/SKILL.md intro line is missing or malformed");
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
totalTools: Number(match[1]),
|
|
56
|
-
uniqueInToolsets: Number(match[2]),
|
|
57
|
-
toolsetCount: Number(match[3]),
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
function parseDestructiveTools(skill) {
|
|
61
|
-
const section = skill.match(/## Destructive Tools[^\n]*\n\n(`[^`]+`(?:, `[^`]+`)*)$/m);
|
|
62
|
-
if (!section) {
|
|
63
|
-
fail("skills/gitlab-mcp/SKILL.md destructive tools section is missing or malformed");
|
|
64
|
-
}
|
|
65
|
-
return new Set([...section[1].matchAll(/`([a-z_]+)`/g)].map((m) => m[1]));
|
|
66
|
-
}
|
|
67
|
-
function collectReferenceToolNames() {
|
|
68
|
-
const toolNames = new Set();
|
|
69
|
-
for (const file of readdirSync(REF_DIR).filter((name) => name.endsWith(".md"))) {
|
|
70
|
-
const text = readFileSync(join(REF_DIR, file), "utf8");
|
|
71
|
-
for (const match of text.matchAll(/`([a-z][a-z0-9_]*)`/g)) {
|
|
72
|
-
const name = match[1];
|
|
73
|
-
if (!REFERENCE_FIELD_ALLOWLIST.has(name)) {
|
|
74
|
-
toolNames.add(name);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return toolNames;
|
|
79
|
-
}
|
|
80
|
-
const skill = readFileSync(SKILL_PATH, "utf8");
|
|
81
|
-
const errors = [];
|
|
82
|
-
const registryCounts = Object.fromEntries(TOOLSET_DEFINITIONS.map((definition) => [definition.id, definition.tools.size]));
|
|
83
|
-
const skillRows = parseToolsetTable(skill);
|
|
84
|
-
if (skillRows.size !== TOOLSET_DEFINITIONS.length) {
|
|
85
|
-
errors.push(`toolset table has ${skillRows.size} rows; registry has ${TOOLSET_DEFINITIONS.length}`);
|
|
86
|
-
}
|
|
87
|
-
for (const definition of TOOLSET_DEFINITIONS) {
|
|
88
|
-
const row = skillRows.get(definition.id);
|
|
89
|
-
if (!row) {
|
|
90
|
-
errors.push(`missing toolset row for ${definition.id}`);
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const actualCount = registryCounts[definition.id];
|
|
94
|
-
if (row.count !== actualCount) {
|
|
95
|
-
errors.push(`${definition.id}: skill says ${row.count}, registry has ${actualCount}`);
|
|
96
|
-
}
|
|
97
|
-
const expectedDefault = DEFAULT_TOOLSET_IDS.has(definition.id);
|
|
98
|
-
if (row.isDefault !== expectedDefault) {
|
|
99
|
-
errors.push(`${definition.id}: skill default=${row.isDefault}, registry default=${expectedDefault}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
for (const id of skillRows.keys()) {
|
|
103
|
-
if (!registryCounts[id]) {
|
|
104
|
-
errors.push(`unknown toolset in skill table: ${id}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const uniqueInToolsets = new Set(TOOLSET_DEFINITIONS.flatMap((definition) => [...definition.tools]))
|
|
108
|
-
.size;
|
|
109
|
-
const intro = parseIntroCounts(skill);
|
|
110
|
-
if (intro.totalTools !== allTools.length) {
|
|
111
|
-
errors.push(`intro total tools: skill says ${intro.totalTools}, registry has ${allTools.length}`);
|
|
112
|
-
}
|
|
113
|
-
if (intro.uniqueInToolsets !== uniqueInToolsets) {
|
|
114
|
-
errors.push(`intro unique toolset tools: skill says ${intro.uniqueInToolsets}, registry has ${uniqueInToolsets}`);
|
|
115
|
-
}
|
|
116
|
-
if (intro.toolsetCount !== TOOLSET_DEFINITIONS.length) {
|
|
117
|
-
errors.push(`intro toolset count: skill says ${intro.toolsetCount}, registry has ${TOOLSET_DEFINITIONS.length}`);
|
|
118
|
-
}
|
|
119
|
-
const skillDestructive = parseDestructiveTools(skill);
|
|
120
|
-
for (const tool of skillDestructive) {
|
|
121
|
-
if (!destructiveTools.has(tool)) {
|
|
122
|
-
errors.push(`destructive list includes non-destructive tool: ${tool}`);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
for (const tool of destructiveTools) {
|
|
126
|
-
if (!skillDestructive.has(tool)) {
|
|
127
|
-
errors.push(`destructive list missing registry tool: ${tool}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const registryToolNames = new Set(allTools.map((tool) => tool.name));
|
|
131
|
-
for (const tool of collectReferenceToolNames()) {
|
|
132
|
-
if (!registryToolNames.has(tool)) {
|
|
133
|
-
errors.push(`reference mentions unknown tool: ${tool}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (errors.length > 0) {
|
|
137
|
-
console.error("skills/gitlab-mcp/ is out of sync with tools/registry.ts:");
|
|
138
|
-
for (const error of errors) {
|
|
139
|
-
console.error(`- ${error}`);
|
|
140
|
-
}
|
|
141
|
-
process.exit(1);
|
|
142
|
-
}
|
|
143
|
-
console.log("skills/gitlab-mcp/ is in sync with tools/registry.ts");
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { allTools } from "../tools/registry.js";
|
|
4
|
-
async function main() {
|
|
5
|
-
const pkgPath = path.resolve(process.cwd(), "package.json");
|
|
6
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
7
|
-
const serverCard = {
|
|
8
|
-
serverInfo: {
|
|
9
|
-
name: pkg.mcpName || pkg.name,
|
|
10
|
-
version: pkg.version,
|
|
11
|
-
},
|
|
12
|
-
authentication: {
|
|
13
|
-
required: true,
|
|
14
|
-
schemes: ["bearer", "oauth2"],
|
|
15
|
-
},
|
|
16
|
-
tools: allTools.map(t => {
|
|
17
|
-
const tool = { ...t };
|
|
18
|
-
if (tool.inputSchema &&
|
|
19
|
-
typeof tool.inputSchema === "object" &&
|
|
20
|
-
"$schema" in tool.inputSchema) {
|
|
21
|
-
const schema = { ...tool.inputSchema };
|
|
22
|
-
delete schema["$schema"];
|
|
23
|
-
tool.inputSchema = schema;
|
|
24
|
-
}
|
|
25
|
-
return tool;
|
|
26
|
-
}),
|
|
27
|
-
resources: [],
|
|
28
|
-
prompts: [],
|
|
29
|
-
};
|
|
30
|
-
const outDir = path.resolve(process.cwd(), ".well-known", "mcp");
|
|
31
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
32
|
-
const outFile = path.join(outDir, "server-card.json");
|
|
33
|
-
fs.writeFileSync(outFile, JSON.stringify(serverCard, null, 2), "utf8");
|
|
34
|
-
console.log(`Successfully generated ${outFile} (${allTools.length} tools)`);
|
|
35
|
-
}
|
|
36
|
-
main().catch(err => {
|
|
37
|
-
console.error("Failed to generate server card:", err);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
/**
|
|
3
|
-
* Generate docs/reference/tool-coverage.md from tools/registry.ts + test/ MCP calls.
|
|
4
|
-
*
|
|
5
|
-
* Detection rules live in ./tool-coverage/coverage.ts (AST-scoped): a tool is
|
|
6
|
-
* invoked when test source sends that name as a `callTool*` argument, as the
|
|
7
|
-
* `name` of a first-argument params object (`client.callTool({ name })`), or as
|
|
8
|
-
* the `name` of a `params` object inside a `tools/call` payload literal.
|
|
9
|
-
*
|
|
10
|
-
* Name-only mentions (toolset tables, description-quality) do not count.
|
|
11
|
-
* callTool(variable) loops are missed unless the name is also a literal in that call.
|
|
12
|
-
*
|
|
13
|
-
* Run with: npm run docs:tools
|
|
14
|
-
*/
|
|
15
|
-
import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
16
|
-
import { dirname, join, relative } from "node:path";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
18
|
-
import { allTools, TOOLSET_DEFINITIONS } from "../tools/registry.js";
|
|
19
|
-
import { assertDetectorHealthy, buildCoverageMarkdown, collectInvocations, countInvoked, groupToolsByToolset, percent, SKIP_FILES, } from "./tool-coverage/coverage.js";
|
|
20
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
-
const REPO_ROOT = join(__dirname, "..");
|
|
22
|
-
const TEST_DIR = join(REPO_ROOT, "test");
|
|
23
|
-
const OUT_PATH = join(REPO_ROOT, "docs", "reference", "tool-coverage.md");
|
|
24
|
-
function walkTestFiles(dir) {
|
|
25
|
-
const out = [];
|
|
26
|
-
for (const name of readdirSync(dir)) {
|
|
27
|
-
const full = join(dir, name);
|
|
28
|
-
const stat = statSync(full);
|
|
29
|
-
if (stat.isDirectory()) {
|
|
30
|
-
out.push(...walkTestFiles(full));
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
if (/\.(ts|js)$/.test(name) && !SKIP_FILES.has(name)) {
|
|
34
|
-
out.push(full);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return out;
|
|
38
|
-
}
|
|
39
|
-
function repoPath(abs) {
|
|
40
|
-
return relative(REPO_ROOT, abs).split("\\").join("/");
|
|
41
|
-
}
|
|
42
|
-
function readScannedFiles() {
|
|
43
|
-
return walkTestFiles(TEST_DIR).map(abs => ({
|
|
44
|
-
path: repoPath(abs),
|
|
45
|
-
text: readFileSync(abs, "utf8"),
|
|
46
|
-
}));
|
|
47
|
-
}
|
|
48
|
-
function main() {
|
|
49
|
-
const toolNames = allTools.map(tool => tool.name);
|
|
50
|
-
const toolNameSet = new Set(toolNames);
|
|
51
|
-
const hits = collectInvocations(readScannedFiles(), toolNameSet);
|
|
52
|
-
const invokedCount = countInvoked(toolNames, hits);
|
|
53
|
-
assertDetectorHealthy(hits, invokedCount);
|
|
54
|
-
const grouped = groupToolsByToolset(toolNames, TOOLSET_DEFINITIONS);
|
|
55
|
-
writeFileSync(OUT_PATH, buildCoverageMarkdown(toolNames, hits, grouped));
|
|
56
|
-
console.log(`generated docs/reference/tool-coverage.md — ${invokedCount}/${toolNames.length} (${percent(invokedCount, toolNames.length)})`);
|
|
57
|
-
}
|
|
58
|
-
main();
|