archdrift 0.1.0__tar.gz
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.
- archdrift-0.1.0/.claude/settings.local.json +12 -0
- archdrift-0.1.0/.github/workflows/ci.yml +41 -0
- archdrift-0.1.0/.gitignore +4 -0
- archdrift-0.1.0/ARCHITECTURE.md +55 -0
- archdrift-0.1.0/LICENSE +21 -0
- archdrift-0.1.0/PKG-INFO +114 -0
- archdrift-0.1.0/README.md +91 -0
- archdrift-0.1.0/pyproject.toml +48 -0
- archdrift-0.1.0/src/archdrift/__init__.py +17 -0
- archdrift-0.1.0/src/archdrift/__main__.py +6 -0
- archdrift-0.1.0/src/archdrift/cli.py +650 -0
- archdrift-0.1.0/structure.json +196 -0
- archdrift-0.1.0/tests/test_lifecycle.py +156 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# CI do archdrift.
|
|
2
|
+
#
|
|
3
|
+
# Dois jobs:
|
|
4
|
+
# 1. test -> pytest em matriz de versões do Python
|
|
5
|
+
# 2. dogfood -> o repo valida a PRÓPRIA arquitetura com o próprio tool.
|
|
6
|
+
# Se este job quebrar, o produto está funcionando. :)
|
|
7
|
+
|
|
8
|
+
name: CI
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [main]
|
|
13
|
+
pull_request:
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.9", "3.11", "3.13"]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
- name: Install
|
|
27
|
+
run: pip install -e ".[dev]"
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: pytest -v
|
|
30
|
+
|
|
31
|
+
dogfood:
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.13"
|
|
38
|
+
- name: Install
|
|
39
|
+
run: pip install -e .
|
|
40
|
+
- name: Architecture drift check (eating our own dog food)
|
|
41
|
+
run: archdrift check .
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Arquitetura — archdrift
|
|
2
|
+
|
|
3
|
+
> Contrato de arquitetura mantido por `archdrift.py`.
|
|
4
|
+
> Seções entre `<!-- map:begin/end -->` são regeneradas; o resto é seu.
|
|
5
|
+
|
|
6
|
+
<!-- map:begin stack -->
|
|
7
|
+
## Stack detectada
|
|
8
|
+
|
|
9
|
+
| Tecnologia | Evidência | O que é |
|
|
10
|
+
|------------|-----------|---------|
|
|
11
|
+
| Python | `pyproject.toml` | manifesto do projeto Python |
|
|
12
|
+
| GitHub Actions | `.github/workflows (1 workflow(s))` | pipelines de CI/CD |
|
|
13
|
+
<!-- map:end stack -->
|
|
14
|
+
|
|
15
|
+
<!-- map:begin tree -->
|
|
16
|
+
## Estrutura de pastas
|
|
17
|
+
|
|
18
|
+
<!-- map:hash 8503e20d6c01 -->
|
|
19
|
+
```
|
|
20
|
+
archdrift/
|
|
21
|
+
├── .github/
|
|
22
|
+
│ └── workflows/
|
|
23
|
+
│ └── ci.yml
|
|
24
|
+
├── src/ # Código-fonte principal da aplicação
|
|
25
|
+
│ └── archdrift/
|
|
26
|
+
│ ├── __init__.py
|
|
27
|
+
│ ├── __main__.py
|
|
28
|
+
│ └── cli.py
|
|
29
|
+
├── tests/ # Testes automatizados
|
|
30
|
+
│ └── test_lifecycle.py
|
|
31
|
+
├── .gitignore
|
|
32
|
+
├── LICENSE
|
|
33
|
+
├── pyproject.toml
|
|
34
|
+
└── README.md
|
|
35
|
+
```
|
|
36
|
+
<!-- map:end tree -->
|
|
37
|
+
|
|
38
|
+
<!-- map:begin contract -->
|
|
39
|
+
## Responsabilidades das pastas
|
|
40
|
+
|
|
41
|
+
<!-- Edite as descrições abaixo: elas são PRESERVADAS entre gerações. -->
|
|
42
|
+
<!-- Linhas com _(preencher)_ são pendências: `check` falha até você preenchê-las. -->
|
|
43
|
+
|
|
44
|
+
| Pasta | Responsabilidade |
|
|
45
|
+
|-------|------------------|
|
|
46
|
+
| `.github` | Automação do GitHub |
|
|
47
|
+
| `.github/workflows` | CI: testes em matriz + dogfood do drift check |
|
|
48
|
+
| `src` | Código-fonte principal da aplicação |
|
|
49
|
+
| `src/archdrift` | Pacote Python: CLI, scan, merge e check |
|
|
50
|
+
| `tests` | Testes automatizados |
|
|
51
|
+
<!-- map:end contract -->
|
|
52
|
+
|
|
53
|
+
## Notas
|
|
54
|
+
|
|
55
|
+
_Espaço livre: decisões de arquitetura, convenções, ADRs. O script nunca toca nesta seção._
|
archdrift-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SEU_NOME
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
archdrift-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: archdrift
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Architecture contract for AI coding agents: a curated, human-edited ARCHITECTURE.md with drift detection in CI.
|
|
5
|
+
Project-URL: Homepage, https://github.com/EvertDeveloper/archdrift
|
|
6
|
+
Project-URL: Issues, https://github.com/EvertDeveloper/archdrift/issues
|
|
7
|
+
Author: Everton Godoi
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agents-md,ai-agents,architecture,claude-code,context-engineering,cursor,documentation,drift-detection
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: build; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: twine; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# archdrift
|
|
25
|
+
|
|
26
|
+
**Architecture contract for AI coding agents.** A curated `ARCHITECTURE.md` that agents read, humans edit, and CI enforces — so your architecture docs never rot.
|
|
27
|
+
|
|
28
|
+
[](https://github.com/SEU_USUARIO/archdrift/actions)
|
|
29
|
+
[](https://pypi.org/project/archdrift/)
|
|
30
|
+

|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## The problem
|
|
36
|
+
|
|
37
|
+
Tools like Repomix and CodeGraph are **descriptive**: they read your code and tell agents what exists. But no tool captures what your architecture is *supposed* to be — the intent behind it. So agents guess, `ARCHITECTURE.md` files rot within weeks, and nobody notices until an agent (or a new dev) builds on top of stale assumptions.
|
|
38
|
+
|
|
39
|
+
## The idea
|
|
40
|
+
|
|
41
|
+
`archdrift` makes your `ARCHITECTURE.md` **normative**:
|
|
42
|
+
|
|
43
|
+
1. **Generated map** — folder tree, detected stack, responsibilities table. Curated for token efficiency: code files listed, assets collapsed.
|
|
44
|
+
2. **Human curation that survives** — edit any description in the responsibilities table, add ADRs and notes anywhere outside the managed sections. Regeneration **never** destroys your edits.
|
|
45
|
+
3. **Drift detection in CI** — `archdrift check` exits 1 when reality diverges from the documented contract. The doc can't rot, because rot breaks the build.
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
┌─────────────┐ generate ┌─────────────────┐ read ┌────────────┐
|
|
49
|
+
│ Filesystem │ ────────────▶ │ ARCHITECTURE.md │ ────────▶ │ AI agent │
|
|
50
|
+
└─────────────┘ │ (you curate) │ └────────────┘
|
|
51
|
+
▲ └─────────────────┘
|
|
52
|
+
│ │ check (CI)
|
|
53
|
+
└───────── drift? exit 1 ◀──────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick start
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uvx archdrift . # or: pipx run archdrift .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This generates `ARCHITECTURE.md` (the contract) and `structure.json` (the graph, for tooling). Folders without a known role get marked `_(preencher)_` — fill them in, they're preserved forever.
|
|
63
|
+
|
|
64
|
+
Then enforce it in CI:
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
# .github/workflows/ci.yml
|
|
68
|
+
- name: Architecture drift check
|
|
69
|
+
run: uvx archdrift check .
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Now every PR that adds an undocumented folder, deletes a documented one, or changes structure without regenerating the map **fails the build** until someone updates the contract.
|
|
73
|
+
|
|
74
|
+
## How merging works
|
|
75
|
+
|
|
76
|
+
Managed sections are delimited by markers:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
<!-- map:begin tree -->
|
|
80
|
+
...regenerated by the tool...
|
|
81
|
+
<!-- map:end tree -->
|
|
82
|
+
|
|
83
|
+
## ADR-001 ← yours, never touched
|
|
84
|
+
|
|
85
|
+
<!-- map:begin contract -->
|
|
86
|
+
| Folder | Responsibility |
|
|
87
|
+
| `src/models` | Prisma entities — NEVER import from controllers | ← your edit, preserved
|
|
88
|
+
<!-- map:end contract -->
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Priority for each folder's description: **your edit** > name-based heuristic > pending placeholder.
|
|
92
|
+
|
|
93
|
+
## Why not just use a repo packer / knowledge graph?
|
|
94
|
+
|
|
95
|
+
Use both. Repomix, CodeGraph, aider's repo-map are excellent at telling agents *what the code is*. `archdrift` covers the piece they can't infer: *what the architecture is meant to be* — and keeps that promise honest via CI. It's `dependency-cruiser` energy, rethought for the agent era, in a single zero-dependency Python file.
|
|
96
|
+
|
|
97
|
+
## Roadmap
|
|
98
|
+
|
|
99
|
+
- [x] Managed sections + merge (human curation survives regeneration)
|
|
100
|
+
- [x] `check` mode — drift detection with meaningful exit codes for CI
|
|
101
|
+
- [x] Stack detection, token-efficient tree (type-aware truncation)
|
|
102
|
+
- [ ] `AGENTS.md` integration (pointer section into the emerging convention)
|
|
103
|
+
- [ ] Declarative rules (`src/controllers must-not-import src/repositories`)
|
|
104
|
+
- [ ] MCP server mode
|
|
105
|
+
- [ ] Semantic graph: declared dependencies vs. real imports — the diff is the product
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install -e ".[dev]"
|
|
111
|
+
pytest -v
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
MIT licensed. Issues and PRs welcome.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# archdrift
|
|
2
|
+
|
|
3
|
+
**Architecture contract for AI coding agents.** A curated `ARCHITECTURE.md` that agents read, humans edit, and CI enforces — so your architecture docs never rot.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/SEU_USUARIO/archdrift/actions)
|
|
6
|
+
[](https://pypi.org/project/archdrift/)
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The problem
|
|
13
|
+
|
|
14
|
+
Tools like Repomix and CodeGraph are **descriptive**: they read your code and tell agents what exists. But no tool captures what your architecture is *supposed* to be — the intent behind it. So agents guess, `ARCHITECTURE.md` files rot within weeks, and nobody notices until an agent (or a new dev) builds on top of stale assumptions.
|
|
15
|
+
|
|
16
|
+
## The idea
|
|
17
|
+
|
|
18
|
+
`archdrift` makes your `ARCHITECTURE.md` **normative**:
|
|
19
|
+
|
|
20
|
+
1. **Generated map** — folder tree, detected stack, responsibilities table. Curated for token efficiency: code files listed, assets collapsed.
|
|
21
|
+
2. **Human curation that survives** — edit any description in the responsibilities table, add ADRs and notes anywhere outside the managed sections. Regeneration **never** destroys your edits.
|
|
22
|
+
3. **Drift detection in CI** — `archdrift check` exits 1 when reality diverges from the documented contract. The doc can't rot, because rot breaks the build.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
┌─────────────┐ generate ┌─────────────────┐ read ┌────────────┐
|
|
26
|
+
│ Filesystem │ ────────────▶ │ ARCHITECTURE.md │ ────────▶ │ AI agent │
|
|
27
|
+
└─────────────┘ │ (you curate) │ └────────────┘
|
|
28
|
+
▲ └─────────────────┘
|
|
29
|
+
│ │ check (CI)
|
|
30
|
+
└───────── drift? exit 1 ◀──────┘
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uvx archdrift . # or: pipx run archdrift .
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This generates `ARCHITECTURE.md` (the contract) and `structure.json` (the graph, for tooling). Folders without a known role get marked `_(preencher)_` — fill them in, they're preserved forever.
|
|
40
|
+
|
|
41
|
+
Then enforce it in CI:
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
# .github/workflows/ci.yml
|
|
45
|
+
- name: Architecture drift check
|
|
46
|
+
run: uvx archdrift check .
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Now every PR that adds an undocumented folder, deletes a documented one, or changes structure without regenerating the map **fails the build** until someone updates the contract.
|
|
50
|
+
|
|
51
|
+
## How merging works
|
|
52
|
+
|
|
53
|
+
Managed sections are delimited by markers:
|
|
54
|
+
|
|
55
|
+
```markdown
|
|
56
|
+
<!-- map:begin tree -->
|
|
57
|
+
...regenerated by the tool...
|
|
58
|
+
<!-- map:end tree -->
|
|
59
|
+
|
|
60
|
+
## ADR-001 ← yours, never touched
|
|
61
|
+
|
|
62
|
+
<!-- map:begin contract -->
|
|
63
|
+
| Folder | Responsibility |
|
|
64
|
+
| `src/models` | Prisma entities — NEVER import from controllers | ← your edit, preserved
|
|
65
|
+
<!-- map:end contract -->
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Priority for each folder's description: **your edit** > name-based heuristic > pending placeholder.
|
|
69
|
+
|
|
70
|
+
## Why not just use a repo packer / knowledge graph?
|
|
71
|
+
|
|
72
|
+
Use both. Repomix, CodeGraph, aider's repo-map are excellent at telling agents *what the code is*. `archdrift` covers the piece they can't infer: *what the architecture is meant to be* — and keeps that promise honest via CI. It's `dependency-cruiser` energy, rethought for the agent era, in a single zero-dependency Python file.
|
|
73
|
+
|
|
74
|
+
## Roadmap
|
|
75
|
+
|
|
76
|
+
- [x] Managed sections + merge (human curation survives regeneration)
|
|
77
|
+
- [x] `check` mode — drift detection with meaningful exit codes for CI
|
|
78
|
+
- [x] Stack detection, token-efficient tree (type-aware truncation)
|
|
79
|
+
- [ ] `AGENTS.md` integration (pointer section into the emerging convention)
|
|
80
|
+
- [ ] Declarative rules (`src/controllers must-not-import src/repositories`)
|
|
81
|
+
- [ ] MCP server mode
|
|
82
|
+
- [ ] Semantic graph: declared dependencies vs. real imports — the diff is the product
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install -e ".[dev]"
|
|
88
|
+
pytest -v
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
MIT licensed. Issues and PRs welcome.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------
|
|
2
|
+
# Empacotamento do archdrift
|
|
3
|
+
#
|
|
4
|
+
# Publicação: python -m build && twine upload dist/*
|
|
5
|
+
# Dev local: pip install -e ".[dev]"
|
|
6
|
+
# Uso final: uvx archdrift . (ou: pipx run archdrift .)
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
[build-system]
|
|
10
|
+
requires = ["hatchling"]
|
|
11
|
+
build-backend = "hatchling.build"
|
|
12
|
+
|
|
13
|
+
[project]
|
|
14
|
+
name = "archdrift"
|
|
15
|
+
version = "0.1.0"
|
|
16
|
+
description = "Architecture contract for AI coding agents: a curated, human-edited ARCHITECTURE.md with drift detection in CI."
|
|
17
|
+
readme = "README.md"
|
|
18
|
+
requires-python = ">=3.9"
|
|
19
|
+
license = { text = "MIT" }
|
|
20
|
+
authors = [{ name = "Everton Godoi" }] # TODO: preencher antes de publicar
|
|
21
|
+
keywords = [
|
|
22
|
+
"ai-agents", "architecture", "documentation", "drift-detection",
|
|
23
|
+
"claude-code", "cursor", "agents-md", "context-engineering",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 3 - Alpha",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"License :: OSI Approved :: MIT License",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Topic :: Software Development :: Documentation",
|
|
31
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
32
|
+
]
|
|
33
|
+
# Zero dependências de runtime — só stdlib. Isso é feature, não acidente:
|
|
34
|
+
# instala em qualquer lugar, roda em qualquer CI, sem supply chain risk.
|
|
35
|
+
dependencies = []
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = ["pytest>=7.0", "build", "twine"]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
archdrift = "archdrift.cli:main"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/EvertDeveloper/archdrift" # TODO: preencher
|
|
45
|
+
Issues = "https://github.com/EvertDeveloper/archdrift/issues"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel]
|
|
48
|
+
packages = ["src/archdrift"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
archdrift — Contrato de arquitetura para agentes de código.
|
|
3
|
+
|
|
4
|
+
API pública mínima: quem quiser usar como biblioteca (em vez de CLI)
|
|
5
|
+
importa daqui. Tudo o mais em cli.py é considerado interno.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from archdrift.cli import (
|
|
9
|
+
main,
|
|
10
|
+
cmd_generate,
|
|
11
|
+
cmd_check,
|
|
12
|
+
scan,
|
|
13
|
+
detect_stack,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__version__ = "0.1.0"
|
|
17
|
+
__all__ = ["main", "cmd_generate", "cmd_check", "scan", "detect_stack"]
|