A commitment tripwire for AI-edited decision docs: flags when a tracked commitment disappears, word-for-word, between two versions. MCP server + Python library. A signal, not a judge.
Project description
Aperture MCP
Did an agent quietly drop a commitment from your spec — and no one noticed?
English · 简体中文
AI agents now rewrite the documents that govern your work — specs, plans, ADRs, charters,
AGENTS.md files. Somewhere in the edit, a constraint you set earlier can quietly disappear.
Aperture MCP is a commitment tripwire. You name the commitments you care about; it flags — word for word — when one of them vanishes between two versions of a decision document.
A signal, not a judge. It trips; you investigate. Opt-in · runs locally · never trains on your data.
What it is (and what it is not)
Aperture MCP is a small tool (and plain Python library) that compares two text states of the same decision — an earlier version and a later one — and surfaces a narrow, specific kind of decision drift: when a tracked commitment’s exact text disappeared.
- ✅ It does: flag when a commitment you listed verbatim is present in version A and gone from version B — across commits, sessions, or authors. It returns a structured, comparable result with its own blind spots written on the label.
- ❌ It does not: understand meaning. It matches text as a case-insensitive substring, so it
misses a commitment that was reworded / softened / paraphrased (it looks dropped-free even
though the promise weakened); it declines/abstains on a commitment that was merely translated
(it can’t compare verbatim across scripts, so it returns
degradedrather than false-flag); and it can still false-flag a commitment that was merely reformatted (the words moved, the meaning didn’t). It does not rank options, score quality, or tell you a change was wrong. That judgment stays with you.
If you want one sentence: Aperture MCP is grep for vanished commitments, wrapped so an agent can
call it mid-task and get a structured answer that admits what it can’t see.
Quickstart (≈2 minutes)
pip install aperture-mcp
Run the bundled example (clone the repo first) — it trips on a dropped commitment against checked-in fixtures, with no setup, no API keys, fully offline:
python3 examples/git_decision_drift/git_decision_drift.py
Aperture MCP · commitment tripwire — a fixture/sample decision-doc edit
[TRIPPED ] 'ci-gates-green' (in_before=True, in_after=False)
[ held ] 'data-never-leaves-device' (in_before=True, in_after=True)
One watched commitment vanished between the two versions; one held.
Aperture MCP makes the disappearance visible — you decide whether it was intended.
Use it from your own code:
from aperture import compare, Anchor, AnchorKind
result = compare(
state_a="We commit to: ci-gates-green before release; data-never-leaves-device.",
state_b="We commit to: data-never-leaves-device.",
anchors=[Anchor(kind=AnchorKind.COMMITMENT, id="ci-gates-green")],
)
print(result.status) # DROPPED_SILENTLY
print(result.anchor_violations) # the commitment that vanished
Wire it into an MCP client (Cursor, Cline, Goose, or any stdio-capable host):
{
"mcpServers": {
"aperture-mcp": { "command": "aperture-mcp" }
}
}
Prefer zero-install? Point the client at
uvxinstead:{ "command": "uvx", "args": ["aperture-mcp"] }.
What trips it — and what slips past
Aperture MCP is a heuristic. We measured it on our own gold corpus and we publish the numbers instead of a single flattering score, because knowing where it’s blind is the product — recall 0.375, precision 0.75 on a 41-case corpus (it catches 9 of 24 real drifts; ~1 flag in 4 is noise), full breakdown in docs/measured-limits.md:
| Kind of change | Does Aperture MCP flag it? |
|---|---|
| A watched commitment deleted verbatim | ✅ Reliably — this is the one thing it’s good at |
| A commitment reworded / softened (“must” → “should”) | ❌ Missed — the text still “matches” |
| A commitment paraphrased / restructured | ❌ Missed |
| A number / scope / negation quietly changed | ❌ Missed |
| A commitment translated to another language | ⚠️ Declines (abstains) for a natural-language anchor — it can’t compare verbatim across scripts, so it returns degraded rather than false-flag (a commitment dropped and translated is missed) |
Anchor style matters for that last row: the abstain applies to a natural-language anchor. A code-identifier anchor (the
ci-gates-greenstyle the quickstart teaches) is treated as translation-stable — Aperture keeps checking it across languages, so if that exact token disappears it still flagsDROPPED_SILENTLY(usually what you want for a stable identifier).
Takeaway: treat every flag as “look here,” never as “this is wrong” — and never assume silence means nothing drifted. Aperture MCP catches the verbatim disappearance case well and is honest that it catches little else. That narrow, reliable signal is useful precisely because it doesn’t pretend to be more.
Hit one of those misses on your own docs? That's the single most useful thing you can send us — report it in ~30s (your wording is optional). Real misses guide what we fix next.
Why not just
git diff? You can reproduce the core check withgrep. What Aperture MCP adds is that an agent can call it mid-task (over MCP), it returns a structured, directional result (ok/degraded/DROPPED_SILENTLY/ …), and it reports its own blind spots in the result so a human can audit the gaps. It’s ergonomics + honesty around a simple, legible check — not a smarter detector.
Why this exists
Long-running and multi-agent workflows drift. A constraint set in turn 3 / session 1 / by agent A gets quietly edited away forty turns later, in another session, by agent B — and nobody notices until it ships. Aperture MCP is a preflight you can put on the documents agents maintain: name the commitments that must not silently vanish, and get a tripwire when one does.
It is deliberately small and legible. It is not an AI that decides for you; it is a signal that helps you stay consistent with yourself.
Who it’s for
Teams and builders who (a) let AI agents edit repo-resident decision documents — specs, plans,
ADRs, charters, and AGENTS.md files — and (b) keep those documents under version control.
If your agents touch text that encodes promises, Aperture MCP gives you a cheap, honest tripwire on the
ones you can’t afford to lose silently.
Privacy
- Opt-in and local. Aperture MCP runs on your machine. It makes no network calls.
- Never trains on your data. Your decision text is yours; it never leaves your process.
- Usage logging is off by default and, when enabled, records only metadata (timestamp, tool, status, counts) — never your decision text or commitment wording.
Honesty about the demo
The repository ships a small hand-authored fixture ADR (a before/after pair under
examples/git_decision_drift/fixtures/), where Aperture MCP
correctly flags a commitment we deliberately retired and stays quiet on one we kept. It is a faithful
illustration of the mechanism — but it is a sample of one that we author and judge ourselves. It
demonstrates how the tripwire works, not that the signal is strong. For the latter, see the
measured per-family numbers above and in
docs/measured-limits.md.
We have zero external adopters yet — if you run Aperture MCP on your own decision docs, we’d love to
hear what it caught and what it missed.
Project status
Early, pre-1.0, not yet a production gate. The compare contract (v0.2) is frozen and covered
by a conformance suite; the package API may still move. See VERSIONING.md for the
compatibility policy and CHANGELOG.md for changes.
Hit a miss? Help it improve
Aperture MCP will miss things — that's by design (it's blind to reworded, softened, and translated commitments). When it misses a drift you cared about, or false-flags a rewrite, telling us is the single most valuable contribution:
- ~30 seconds, no account/usage data, your wording is optional → open a drift-case report.
- Real misses tell us which blind spot to fix next, and — only if you choose to share the wording —
can become cases in the gold corpus that keeps the numbers in
docs/measured-limits.mdhonest.
We never auto-collect anything (see Privacy); this happens only when you choose to share. Questions, or "is this the right tool for my case?" → GitHub Discussions.
More ways to help: CONTRIBUTING.md.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aperture_mcp-0.1.0.tar.gz.
File metadata
- Download URL: aperture_mcp-0.1.0.tar.gz
- Upload date:
- Size: 90.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
237bfad2ef86bf6951f105d8eff06daa17a43c3e9201208f9fa283d23807cafd
|
|
| MD5 |
8117bad02b9e688d12c28f807244cab3
|
|
| BLAKE2b-256 |
9e5e0dad67d4f567a217e4cf27a98dbdf1c638b1e7db4485bcd6266c904132b0
|
Provenance
The following attestation bundles were made for aperture_mcp-0.1.0.tar.gz:
Publisher:
publish.yml on jaysinailabs/aperture-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aperture_mcp-0.1.0.tar.gz -
Subject digest:
237bfad2ef86bf6951f105d8eff06daa17a43c3e9201208f9fa283d23807cafd - Sigstore transparency entry: 2046724982
- Sigstore integration time:
-
Permalink:
jaysinailabs/aperture-mcp@3262f9da70fb25e8f9cf8f561c18d138770425af -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jaysinailabs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3262f9da70fb25e8f9cf8f561c18d138770425af -
Trigger Event:
push
-
Statement type:
File details
Details for the file aperture_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aperture_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 54.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b588af63a420c269afa319061dcd0a787695bbc732a3548fe35009bdedb45de8
|
|
| MD5 |
34051dee3b01ee63aa35f4c1584ebb9f
|
|
| BLAKE2b-256 |
405add28823c8d75b035ff0d75dac27df1af07131cb5b06ccd5a53f6f7e11511
|
Provenance
The following attestation bundles were made for aperture_mcp-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on jaysinailabs/aperture-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aperture_mcp-0.1.0-py3-none-any.whl -
Subject digest:
b588af63a420c269afa319061dcd0a787695bbc732a3548fe35009bdedb45de8 - Sigstore transparency entry: 2046724995
- Sigstore integration time:
-
Permalink:
jaysinailabs/aperture-mcp@3262f9da70fb25e8f9cf8f561c18d138770425af -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jaysinailabs
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3262f9da70fb25e8f9cf8f561c18d138770425af -
Trigger Event:
push
-
Statement type: