Reference validator + resolver for AIGX (AI Genome Exchange) — the open context format for AI coding agents. Zero dependencies.
Project description
aigx-lint
A tiny, zero-dependency (Python 3.8+ stdlib) validator and resolver for AIGX genomes. It exists to kill the two most common objections to a centralized context format - "it rots" and "it won't scale" - by making both mechanically false.
Why
- It can't rot silently.
aigx-lintchecks the genome against the actual repository: every<file path>must still exist on disk, and every<check>id must resolve to a real<rule>. Run it in CI or a pre-commit hook and a moved/renamed file fails the build until its entry is fixed - the same discipline teams already use forCODEOWNERSandtsconfigpath maps. - It scales by resolution, not ingestion.
--resolve PATHreturns just one file's entry, so an agent's context cost is O(1) per edited file, independent of index size. A 50,000-entry index is one lookup. - It understands hierarchical genomes. Every
.aigx/directory under the root is discovered; eachfiles.aigxindexes its own subtree (see SPEC §8).
Usage
# Validate the genome(s) under the current repo. Exits non-zero on errors (CI-friendly).
python aigx_lint.py --root .
# Print just one file's boundary entry - constant-cost lookup an agent/MCP can call.
python aigx_lint.py --resolve src/features/meetings/bookMeeting.ts --root .
# Machine-readable output for MCP servers, editor extensions, and agent wrappers.
python aigx_lint.py --resolve src/features/meetings/bookMeeting.ts --root . --format json
# Summary: genomes, rules, entries, and the all-important forbid scarcity.
python aigx_lint.py --stats --root .
--resolve returns exit code 0 when the target file exists even if the genome has no matching
<file> entry; that is an informational "no boundary indexed yet" result, not a tool failure. It returns
exit code 2 when the target path itself does not exist.
What validation catches
| Check | Why it matters |
|---|---|
<file path> exists on disk |
catches renamed/moved/deleted files → the genome can't go stale unnoticed |
every <check> id resolves to a <rule> |
catches dangling references when a rule is renamed/removed |
duplicate <file> entries (warning) |
catches copy-paste drift across shards |
JSON shape
JSON output is intentionally small and stable so MCP bridges can inject AIGX context without scraping XML:
{
"found": true,
"path": "src/features/meetings/bookMeeting.ts",
"domain": "meetings",
"role": "Book a meeting (validate slot + contact)",
"forbid": { "priority": "CRIT", "text": "NEVER import internal suppliers modules" },
"gotcha": { "priority": null, "text": "Use the public suppliers API for contact email" },
"checks": ["ARCH-no-deep-imports", "DATA-integer-cents"],
"block": "<file path=\"...\">...</file>"
}
When there is no indexed boundary for an existing file, found is false and exists is true.
Try it on
examples/sourcing-app/:--statsand--resolvework directly;--validatewill (correctly!) report thesrc/**paths as missing, because that example ships only the genome, not the application source - which is exactly the "moved/missing file" signal the linter is built to catch. Run it against a real checkout to see it pass clean.
CI examples
GitHub Actions:
name: aigx
on: [push, pull_request]
jobs:
lint-genome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.x" }
- run: python tools/aigx-lint/aigx_lint.py --root .
GitLab CI:
aigx-lint:
image: python:3.12-slim
script:
- python tools/aigx-lint/aigx_lint.py --root .
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
Bitbucket Pipelines:
pipelines:
default:
- step:
name: Lint AIGX genome
image: python:3.12-slim
script:
- python tools/aigx-lint/aigx_lint.py --root .
Pre-commit hook (catches issues before they reach CI):
# Install once: copy to .git/hooks/pre-commit and make it executable
#!/usr/bin/env bash
set -e
python tools/aigx-lint/aigx_lint.py --root .
chmod +x .git/hooks/pre-commit
Or use pre-commit framework with a local hook:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: aigx-lint
name: Lint AIGX genome
entry: python tools/aigx-lint/aigx_lint.py --root .
language: python
pass_filenames: false
always_run: true
That's the whole answer to "decoupled docs rot": don't decouple and walk away - decouple and lint.
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 aigx-1.2.0.tar.gz.
File metadata
- Download URL: aigx-1.2.0.tar.gz
- Upload date:
- Size: 23.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56328d44abd05745e060134590fed463bad0bd29759597d9df94b1c03275cf01
|
|
| MD5 |
d2bc2b6d7058ab1bd1ee68fd04843ef2
|
|
| BLAKE2b-256 |
88dffe35297e31ea1e7f73f8b610e115429992b678b5c56144553836ca21d68f
|
File details
Details for the file aigx-1.2.0-py3-none-any.whl.
File metadata
- Download URL: aigx-1.2.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f7c7f825730ccb16cd7ff54c0b6086f7bd535e265f2068be44f9d23e6ec23fb
|
|
| MD5 |
180f428c23a20f71a99247ee156cbb93
|
|
| BLAKE2b-256 |
09589fbdbe85f31a72f2f4da189b0e31ac85069accd3e4d9c409bdaf0d73ed55
|