Skip to content
This repository was archived by the owner on Oct 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions .gitpin/change-evidence.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,58 @@
{
"schemaVersion": 1,
"summary": "Let the Validate workflow be dispatched on main, because auto-merged commits pushed with GITHUB_TOKEN never start the push: main run; the CI routing check now requires the trigger.",
"summary": "Rewrite the README for a fast first read (problem, 30-second fail-to-pass quickstart, film, Mermaid trust-boundary sketch, guardrails, stage-neutral status) and add the social preview and demo GIF it references.",
"claims": [
{
"id": "VALIDATE-DISPATCH-ON-MAIN",
"statement": ".github/workflows/ci.yml adds workflow_dispatch so main can be validated at its exact merged SHA, and scripts/verify-ci-runner-routing.mjs fails if ci.yml ever drops that trigger.",
"id": "README-FIRST-READ",
"statement": "README.md now leads with the problem, a pnpm demo:gate quickstart, use-in-your-repo steps, a Mermaid sketch of the base-trusted policy and head-submitted manifest, guardrails and non-goals, and keeps the stage-neutral 0.6.4 sentence required by scripts/verify-release-tag.mjs.",
"covers": [
".github/workflows/ci.yml",
"scripts/verify-ci-runner-routing.mjs"
"README.md"
],
"evidence": [
{
"ref": "head",
"path": ".github/workflows/ci.yml",
"lineStart": 10,
"lineEnd": 10,
"contentSha256": "31ef10165fe98492a75234e221d538925dc4007bfd24de8f56275ef977e9f564"
"path": "README.md",
"lineStart": 38,
"lineEnd": 38,
"contentSha256": "d3088a4ed3623c123bbc6615dce53fc46ac9c61666bd84fd1231e0c49ba82132"
},
{
"ref": "head",
"path": "scripts/verify-ci-runner-routing.mjs",
"lineStart": 46,
"lineEnd": 46,
"contentSha256": "7c8cbd587163ebb59858ea291e2ec5615475e89f9721728c5d6f5929b28ea39b"
"path": "README.md",
"lineStart": 43,
"lineEnd": 43,
"contentSha256": "a0a4d4a60b7eb8343c9a0021ec8237f9cbdc088d03c4c6bcd0ffd4c70d92d67c"
},
{
"ref": "head",
"path": "README.md",
"lineStart": 184,
"lineEnd": 184,
"contentSha256": "06fa519f1345a104f9fc86974955bc236498b11ae67e363335cc2887a94efef2"
}
]
},
{
"id": "README-MEDIA",
"statement": "The social preview image and the demo GIF are referenced from the README; the GIF is cut from the delivered 30-second film and the preview is rendered from a real film frame.",
"covers": [
"docs/media/social-preview.png",
"docs/media/gitpin-demo.gif"
],
"evidence": [
{
"ref": "head",
"path": "README.md",
"lineStart": 3,
"lineEnd": 3,
"contentSha256": "8a856a365aea603fe62f31cbd6e285d0acb04f352a6667701f760ea7813cf968"
},
{
"ref": "head",
"path": "README.md",
"lineStart": 68,
"lineEnd": 68,
"contentSha256": "98a2d7c9416a700e619964b9069a5a7f6d7892ff032e6e0e4450f38c818cefd1"
}
]
}
Expand Down
243 changes: 168 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,102 +1,194 @@
<div align="center">

<img src="docs/media/social-preview.png" alt="GitPin: agent pull requests must show exact evidence before they merge." width="100%">

# GitPin

### Agent-authored pull requests must show exact evidence before they merge.

**A read-only PR gate and local MCP server that ties every claim an AI agent makes about its change to an exact committed line that anyone can re-check with plain `git`.**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Limit the guarantee to claims committed in the manifest

Neither the gate nor the MCP reads an agent's pull-request description or conversation, so it cannot tie every claim the agent makes to evidence. The gate validates only claims the submitter chose to place in .gitpin/change-evidence.json; omitted prose claims remain invisible even when all policy-required paths are covered. Constrain this value proposition to manifest claims rather than promising enforcement over every agent claim.

Useful? React with 👍 / 👎.


[![Validate](https://github.com/shmindmaster/gitpin/actions/workflows/ci.yml/badge.svg)](https://github.com/shmindmaster/gitpin/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/gitpin.svg)](https://www.npmjs.com/package/gitpin)
[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-io.github.shmindmaster%2Fgitpin-blue.svg)](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.shmindmaster/gitpin&limit=20)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](package.json)
[![MCP Protocol](https://img.shields.io/badge/MCP_SDK-1.32-blue.svg)](https://modelcontextprotocol.io)
[![npm](https://img.shields.io/npm/v/gitpin.svg)](https://www.npmjs.com/package/gitpin)

### Make agent-authored changes show exact evidence before merge.
[Quickstart](#quickstart-the-gate-in-30-seconds) · [Watch the film](#see-it-run) · [Use it in your repo](#use-it-in-your-repo) · [How it works](#how-it-works) · [Guardrails](#guardrails-and-non-goals) · [Status](#status-and-limits)

**GitPin is an agent-delivery assurance gate with a local evidence MCP.** It makes material PR claims cover the actual diff and point to exact committed line slices. The local MCP supplies index-free, read-only, multi-repo evidence that humans and CI can re-check with `git show`.
</div>

**Public-good thesis:** evidence for agent-authored software changes should remain inspectable with ordinary local Git, independent of the coding agent or proprietary hosted platform that produced the change.
---

```text
Agent claim
→ pin.search_* (candidates only)
→ pin.prove (evidence pack: path + line + full SHA + content hash)
→ pin.verify (git show re-check; HEAD match report)
→ you run: git show <sha>:<path>
```
## Why it exists

| Crowded category | GitPin product |
| --- | --- |
| Vector / SQLite “repo context” servers | **No embeddings, no DB, no reindex** |
| Filesystem MCP (writes) | **Never writes indexed repos** |
| One-shot repo dumps | **Live prove → verify MCP loop** |
| Grep hits as “the answer” | **Candidates → evidence pack → verification report** |
| GitHub platform MCP | **Local Git roots (private/offline)** |
Coding agents now open pull requests with confident descriptions: "added retry
logging", "updated the protocol doc", "no other files touched". A reviewer who
wants to trust one of those sentences has to open the file and hunt for the
line, then do it again for the next sentence. Most reviewers stop checking, and
an agent can change a file it never mentions.

Formerly RepoContext 0.3.x. See [migration](docs/migration-gitpin.md).
GitPin turns the description into evidence. The agent commits a small manifest
in which every material claim names the paths it covers and points at an exact
line slice with a SHA-256 of its text. A required check compares that manifest
with the real diff. Any changed file that no claim covers fails the build, and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Qualify the gate's coverage as policy-scoped

With the policy users are told to copy below, not every changed file is checked: templates/gate.yml excludes package.json and docs/generated/**, and src/gate.ts removes excluded paths from requiredPaths before computing uncovered changes. A PR changing only one of those paths can therefore pass without a claim, so this statement overstates what the required check guarantees; describe coverage as applying to every policy-required changed file and make the same qualification in the diagram.

Useful? React with 👍 / 👎.

every claim that passes can be re-checked by a human with `git show`, without
GitPin, without the agent and without a hosted platform.

## Required PR evidence gate
## Quickstart: the gate in 30 seconds

```bash
gitpin gate --base <full-base-sha> --head <full-head-sha>
git clone https://github.com/shmindmaster/gitpin.git && cd gitpin
corepack enable && pnpm install --frozen-lockfile
pnpm demo:gate
```

`demo:gate` builds GitPin, creates a throwaway synthetic repository in a temp
folder, and runs the real `gitpin gate` twice. The agent's first commit changes
`docs/protocol.md` without claiming it, so the gate fails with exit `1`. The
agent adds one evidence locator (line 5, hashed) and the same gate passes with
exit `0`:

```text
$ gitpin gate --base <base> --head <agent-commit>
status: failed exit code: 1
violation: uncovered-change: Changed path has no material claim: docs/protocol.md.
covered: synthetic-service/docs/overview.md:3 @ <agent-commit> (verified)
$ gitpin gate --base <base> --head <locator-commit>
status: ok exit code: 0
covered: synthetic-service/docs/overview.md:3 @ <locator-commit> (verified)
covered: synthetic-service/docs/protocol.md:5 @ <locator-commit> (verified)
```

The gate reads policy only from the trusted base commit, reads the submitted manifest only from the head commit, compares the merge-base diff, and verifies exact line-slice hashes. It never executes PR code and never labels a locator match as proof of semantic correctness. Use the [GitPin GitHub Action setup](docs/pr-evidence-gate.md) to make it a required check. That guide also documents an optional, separate CrewScore check for teams that want written-control coverage alongside GitPin evidence verification.
Nothing is written outside the temp folder, and the folder is removed afterward.

## See it run

<a href="https://saroshhussain.com/films/gitpin-the-gate-that-wants-evidence.mp4">
<img src="docs/media/gitpin-demo.gif" alt="GitPin demo: the gate fails an agent pull request that changed an unclaimed file, then passes after one hashed line locator is added." width="100%">
</a>

> **Versioned distribution:** This source tree and its packed documentation describe GitPin 0.6.4 without asserting publication status. Availability is established only by independently verifying the npm, MCP Registry, GitHub Release, and Pages receipts. Install with `npx -y gitpin@0.6.4` only after the npm receipt resolves. Node 20+.
**[Watch the 90-second film →](https://saroshhussain.com/films/gitpin-the-gate-that-wants-evidence.mp4)** ·
**[The 30-second cut →](https://saroshhussain.com/films/gitpin-the-gate-in-30-seconds.mp4)**

GitPin is maintained by **Sarosh Hussain**, an independent open-source maintainer who leads the project's technical direction.
## Use it in your repo

## Five-minute path
**1. Install the trusted policy on your default branch** (a separate, reviewed
change, so a pull request can never weaken its own gate):

```bash
# From a committed Git repository
# This exact version becomes usable only after npm publication is verified.
npx -y gitpin@0.6.4 init --client codex
mkdir -p .gitpin
curl -fsSL https://raw.githubusercontent.com/shmindmaster/gitpin/v0.6.4/templates/gate.yml -o .gitpin/gate.yml
```

`init` creates `~/.gitpin/repositories.yaml` **outside** the repo, runs `doctor`, prints a **first evidence line with full SHA**, and paste-ready MCP config. It never edits the indexed repository.
**2. Make it a required check:**

```yaml
name: Agent delivery assurance
on: pull_request # never pull_request_target
permissions:
contents: read
jobs:
evidence:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- uses: shmindmaster/gitpin@514799cb0eae55e965e51d510d5e7a0a7604c9cc # v0.6.4
with:
base-sha: ${{ github.event.pull_request.base.sha }}
head-sha: ${{ github.event.pull_request.head.sha }}
```

**3. Each agent PR commits `.gitpin/change-evidence.json`**, starting from
[`templates/change-evidence.json`](templates/change-evidence.json). The full
setup, including rulesets, is in [docs/pr-evidence-gate.md](docs/pr-evidence-gate.md).

**Give your agent the evidence tools.** The local MCP server lets Claude Code,
Codex, Cursor and other MCP clients find candidates and produce the evidence
packs the gate checks:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Explain that evidence packs must be converted to a manifest

The gate does not accept the evidence-pack shape returned by pin.prove; it exclusively reads .gitpin/change-evidence.json, whose claims require fields such as id, covers, ref, path, and lineStart that are absent or differently named in an evidence pack. Saying the MCP produces packs “the gate checks” suggests direct compatibility and leaves users without the required transformation step; state that agents must use pack fields to author the gate manifest.

Useful? React with 👍 / 👎.


```bash
# Independently verify any claim (same contract as pin.verify)
# This exact version becomes usable only after npm publication is verified.
npx -y gitpin@0.6.4 verify \
--repository my-service \
--path docs/architecture.md \
--line 42 \
--sha <full-or-short-hex>
# Run inside any committed Git repository
npx -y gitpin@0.6.4 init --client codex # or claude-code, cursor, windsurf, zed, continue
```

`init` writes `~/.gitpin/repositories.yaml` outside the repository, runs
`doctor`, prints a first evidence line with a full SHA, and prints paste-ready
MCP config. It never edits the repository it registers.

## How it works

```mermaid
flowchart LR
subgraph BASE["Trusted: base commit"]
POL[".gitpin/gate.yml<br/>policy"]
end
subgraph HEAD["Submitted: head commit"]
MAN[".gitpin/change-evidence.json<br/>claims → path, lines, sha256"]
end
DIFF["git diff merge-base..head<br/>the real change"]
POL --> GATE{"gitpin gate<br/>read-only, never runs PR code"}
MAN --> GATE
DIFF --> GATE
GATE -- "uncovered path, wrong hash,<br/>sensitive path" --> FAIL(["exit 1: check fails"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope the sensitive-path failure to evidence locators

The diagram makes sensitive path look like a failure condition for any changed or covered path. In src/gate.ts, however, isAlwaysSensitivePath is applied only to locator.path; a sensitive changed path can be named in covers and paired with evidence from another file without producing this violation. Since the documented boundary is blocking sensitive paths at read time, label this as a sensitive evidence locator rather than implying the gate rejects such changes.

AGENTS.md reference: AGENTS.md:L54-L54

Useful? React with 👍 / 👎.

GATE -- "every changed path covered,<br/>every slice re-hashed" --> PASS(["exit 0: report with full-SHA citations"])
PASS -.-> HUMAN(["Reviewer: git show &lt;sha&gt;:&lt;path&gt;"])
```

## Product job
The gate reads policy only from the trusted base commit and the manifest only
from the head commit, through `git show`, never from a working tree. It compares
the merge-base diff, re-hashes every cited line slice, and emits a report whose
citations carry full SHAs.

**When** agents invent file contents, mix dirty worktrees, or cite the wrong branch
**You want** every fact re-checkable with `git show <sha>:<path>`
**GitPin** registers local Git roots, serves **HEAD-only** docs/code, flags **stale** tracked docs, returns **path / line / SHA**, and closes the loop with **`pin.verify`**.
The MCP side follows one loop. Search returns candidates, never answers. Proof
turns a candidate into an evidence pack. Verification re-checks it with
`git show`:

### Agent tool surface (`pin.*`) — 12 read-only tools
```text
pin.search_docs / pin.search_code candidates only, with a forced next step
→ pin.prove evidence pack: path, line, full SHA, content hash
→ pin.verify independent git show re-check, HEAD match report
→ you: git show <sha>:<path>
```

| Job | Tools |
| Job | Tools (12, all read-only) |
| --- | --- |
| Discover | `pin.catalog` |
| Find candidates | `pin.search_docs`, `pin.search_code` |
| Prove | `pin.prove` (primary), `pin.prove_set` (1–8 cites), `pin.get_doc`, `pin.read` |
| Prove | `pin.prove`, `pin.prove_set` (1 to 8 cites), `pin.get_doc`, `pin.read` |
| Verify | `pin.verify`, `pin.verify_set` |
| Decide | `pin.analyze` → `EvidenceBrief` |
| Inspect / diff | `pin.inspect`, `pin.compare` |
| Decide | `pin.analyze` → `EvidenceBrief` (known facts, gaps, stable `evidenceSetId`) |
| Inspect and diff | `pin.inspect`, `pin.compare` |

Resource `gitpin://catalog`; prompt `prove-with-git-head`. Cite formats are in
[docs/cite-spec.md](docs/cite-spec.md); an agent skill template is in
[templates/gitpin-skill.md](templates/gitpin-skill.md).

Resource: `gitpin://catalog`. Prompt: `prove-with-git-head` (forces the product loop).
Cite formats: [docs/cite-spec.md](docs/cite-spec.md). Agent skill template: [templates/gitpin-skill.md](templates/gitpin-skill.md).
## Guardrails and non-goals

### Functionality that is the pivot (not a rename)
- **Read-only, always.** GitPin never writes, commits or pushes to a repository it reads, and the gate never executes pull-request code.
- **A PR cannot weaken its own gate.** Policy comes from the base commit; evidence comes from the head commit; the dirty working tree is never read.
- **Uncommitted work is never evidence.** Dirty and untracked content is excluded from HEAD citations.
- **Sensitive paths stay sensitive.** Deny rules apply to evidence, and the manifest cannot cite itself.
- **Candidates are not claims.** Search output is labelled `evidence-candidates` and must go through `pin.prove`.
- **No embeddings, no database, no reindex.** Evidence comes from Git objects, so it works offline and on private repositories.

- **Evidence pack** (`pin.prove`): claim binding, line slice, full SHA, `contentSha256`, `citation.cite` / `handle`, next-step verify.
- **Multi-cite sets** (`pin.prove_set` / `pin.verify_set`): stable `evidenceSetId` for multi-repo answers and CI.
- **Verification report** (`pin.verify` / CLI): independent `git show`; optional `mustContain` claim-text; status includes `contradicted`.
- **Candidates, not claims**: search returns `kind: evidence-candidates` with forced `next: pin.prove`.
- **EvidenceBrief**: multi-repo knownFacts / gaps / stable `evidenceSetId` (schema v2).
- **Dirty exclusion**: uncommitted work is never cited as HEAD evidence.
Not goals: semantic search, writing or committing code, replacing GitHub
Issues or PR automation, or treating a non-Git folder as one repository.

### Explicit non-goals
## Status and limits

- Semantic / embedding search
- Writing, committing, or pushing
- Replacing GitHub Issues/PRs automation
- Indexing non-Git umbrella folders as one “repo”
This source tree and its packed documentation describe GitPin 0.6.4 without asserting publication status. Check each channel independently: [npm](https://www.npmjs.com/package/gitpin), the [MCP Registry](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.shmindmaster/gitpin&limit=20) (`io.github.shmindmaster/gitpin`) and [GitHub Releases](https://github.com/shmindmaster/gitpin/releases/tag/v0.6.4).
Node 20 or later. Site: [shmindmaster.github.io/gitpin](https://shmindmaster.github.io/gitpin/).

GitPin verifies **coverage, location, revision and content hash**. It proves
what was committed, not that a claim is true: it does not establish semantic
correctness, runtime behavior, authorship, authorization or compliance. That
judgment stays with the reviewer, who now reads one cited line instead of
hunting for it. Planned work is in the [roadmap](ROADMAP.md).

## Configuration

Expand All @@ -109,23 +201,24 @@ Cite formats: [docs/cite-spec.md](docs/cite-spec.md). Agent skill template: [tem

Default registry: `~/.gitpin/repositories.yaml` (legacy compatibility fallback: `~/.repocontext/...` if present).

## Docs

[Tools](docs/tools.md) · [Compare](docs/compare.md) · [FAQ](docs/faq.md) · [Migration](docs/migration-gitpin.md) · [Clients](docs/clients.md) · [Architecture](docs/architecture.md) · [Roadmap](ROADMAP.md) · [Governance](GOVERNANCE.md) · [Security](SECURITY.md) · [Competitive landscape](docs/research/competitive-landscape-corrected-2026-07-30.md)
Formerly RepoContext 0.3.x. See [migration](docs/migration-gitpin.md).

Site: [shmindmaster.github.io/gitpin](https://shmindmaster.github.io/gitpin/). GitPin is the canonical product and repository name; legacy `repocontext` references exist only for migration compatibility.
## Docs

## Development
[Tools](docs/tools.md) · [PR evidence gate](docs/pr-evidence-gate.md) · [Clients](docs/clients.md) · [Architecture](docs/architecture.md) · [Compare](docs/compare.md) · [FAQ](docs/faq.md) · [Troubleshooting](docs/troubleshooting.md) · [Roadmap](ROADMAP.md) · [Governance](GOVERNANCE.md)

```bash
corepack enable
pnpm install --frozen-lockfile
pnpm validate
pnpm build
pnpm verify:package
pnpm site:test
```
## Contributing, security and license

## License
- **Contributing:** start with an issue for bugs and proposals, then follow
[CONTRIBUTING.md](CONTRIBUTING.md). Good first issues are labelled
[`good first issue`](https://github.com/shmindmaster/gitpin/labels/good%20first%20issue).
Before a pull request: `pnpm validate && pnpm build && pnpm verify:package`.
- **Security:** report vulnerabilities privately through a
[GitHub security advisory](https://github.com/shmindmaster/gitpin/security/advisories/new),
as described in [SECURITY.md](SECURITY.md). Please do not open a public issue.
- **License:** [MIT](LICENSE).

[MIT](LICENSE)
Created and maintained by [Sarosh Hussain](https://saroshhussain.com). Related
open source: [Assay](https://github.com/shmindmaster/assay) keeps an agent's
decision out of its side effects; [CrewScore](https://github.com/shmindmaster/crewscore)
checks whether an agent's prompt writes its safeguards down.
Binary file added docs/media/gitpin-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/media/social-preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading