contribpath
README.md
# contribpath
A CONTRIBUTING guide can read beautifully and still leave
a new contributor stranded, because the document and the
repository's real requirements drift apart: the guide
never mentions the DCO sign-off the CI enforces, or the
changeset the release bot demands. contribpath measures
that drift. You supply the document text and the gates
the repository actually has — each with an id, the label
as it would appear in the document, and any alternative
phrases that also count — and it reports which gates are
documented, which are missing, how much coverage that
adds up to, and a verdict.
Matching is deliberately simple and auditable. Everything
is lowercased, and a gate counts as documented when the
document contains its label or at least one of its
non-empty keywords as a substring. Empty keywords are
ignored on purpose: an empty string is a substring of
every document, so counting it would mark every gate as
covered and hide exactly the gaps this tool exists to
find. Either signal is enough on its own — a gate whose
label never appears can still be covered by a keyword,
and a gate with no keywords at all is covered by its
label alone.
Coverage is `Math.round(100 * documented / gate_count)`,
so two of three gates is 67, not 66. A coverage of 100
reads as `complete`, 60 and up as `partial`, and anything
below 60 as `sparse`. The documented and missing lists
carry gate ids in the order the gates were supplied, so
the report lines up with the caller's own gate list.
If the caller also extracted topics from the document,
they can be passed as `documented_topics` to find the
ones that correspond to no gate at all. A topic matches a
gate when it is exactly that gate's id, or when it equals
the gate's label ignoring case; topics matching nothing
come back verbatim, in input order, as `extra_topics`.
When no topics are supplied, `extra_topics` is empty.
Duplicate gate ids are an error naming the id — a gate
set with two entries for the same gate would make the
coverage number meaningless. Malformed input — a missing
or non-string `document`, a missing or empty `gates`
array, a gate with a missing, empty, or non-string `id`
or `label`, a `keywords` value that is not an array of
strings, or a `documented_topics` entry that is not a
non-empty string — is a validation error naming the
offending path, with no partial result. Unknown extra
fields are ignored, including inside gate items. The
computation is pure and local: no network, no
configuration, and no repository is read or touched.
contribpath compares what you give it; extracting the
gates from a repository in the first place is a separate
job.
## CLI
```bash
npx @reneturcios/contribpath check --input args.json
npx @reneturcios/contribpath --version
```
`args.json` contains the full arguments object:
```json
{
"document": "Please sign off your commits (DCO) and add a changeset.",
"gates": [
{ "id": "dco", "label": "Developer Certificate of Origin", "keywords": ["dco", "sign off"] },
{ "id": "changeset", "label": "Changeset" },
{ "id": "cla", "label": "Contributor License Agreement", "keywords": ["cla"] }
],
"documented_topics": ["dco", "Changeset", "Code of Conduct"]
}
```
The result is printed as JSON:
```json
{
"documented": ["dco", "changeset"],
"missing": ["cla"],
"extra_topics": ["Code of Conduct"],
"coverage_percent": 67,
"verdict": "partial",
"gate_count": 3
}
```
An empty `document` string is valid input: every gate is
missing and the verdict is `sparse`. Exit codes: `0` on
success, `1` on a runtime error (including an unreadable
or invalid input file, or invalid input), `2` on a usage
error.
## MCP server
```bash
npx -y @reneturcios/contribpath mcp
```
MCP client config:
```json
{
"mcpServers": {
"contribpath": {
"command": "npx",
"args": ["-y", "@reneturcios/contribpath", "mcp"]
}
}
}
```
### Tools
- `check_contributing_coverage` — Check a CONTRIBUTING
document against the repository's actual contribution
gates.
- `document` (string, required, may be empty) — the
contributing document text to check
- `gates` (array, required, at least 1 item) — the
repository's actual contribution gates; each item is
an object with:
- `id` (string, required, non-empty) — gate
identifier
- `label` (string, required, non-empty) — gate label
as it would appear in the document
- `keywords` (array of strings, optional) —
alternative phrases that also count as documenting
the gate
- `documented_topics` (array of strings, optional) —
topics the caller extracted from the document,
checked against the gate set
Returns `{documented, missing, extra_topics,
coverage_percent, verdict, gate_count}`.
## Docker
```bash
docker run -i ghcr.io/cloudcorprecords/contribpath
docker run --rm -v "$PWD:/w" ghcr.io/cloudcorprecords/contribpath check --input /w/args.json
```
## Development
```bash
npm install
npm run build # tsc -> dist/
npm test # tsx --test test/*.test.ts (pure local, no network)
npm run dev # run the CLI from source
```
## License
MIT — Copyright (c) 2026 Rene Turcios
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues