adda 0.4.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.
Files changed (68) hide show
  1. adda-0.4.0/.gitignore +31 -0
  2. adda-0.4.0/LICENSE +21 -0
  3. adda-0.4.0/OKF_SCHEMA.md +168 -0
  4. adda-0.4.0/PKG-INFO +349 -0
  5. adda-0.4.0/README.md +316 -0
  6. adda-0.4.0/adda/API_CONTRACTS.md +16 -0
  7. adda-0.4.0/adda/ARCHITECTURE.md +36 -0
  8. adda-0.4.0/adda/DECISIONS/0001-record-architecture-decisions.md +17 -0
  9. adda-0.4.0/adda/DECISIONS/0002-templates-inside-package.md +20 -0
  10. adda-0.4.0/adda/DECISIONS/0003-eval-deterministic-offline.md +21 -0
  11. adda-0.4.0/adda/DECISIONS/0004-compress-opt-in.md +21 -0
  12. adda-0.4.0/adda/DECISIONS/0005-okf-schema-locked-v0.2.md +21 -0
  13. adda-0.4.0/adda/DECISIONS/0006-headroom-optional-ponytail-buildtime.md +21 -0
  14. adda-0.4.0/adda/DECISIONS/0007-enforcement-mechanical-commit-scoped.md +45 -0
  15. adda-0.4.0/adda/DECISIONS/0009-discovery-reports-its-guesses.md +65 -0
  16. adda-0.4.0/adda/DECISIONS/0010-ancestry-staleness-limit-is-published.md +46 -0
  17. adda-0.4.0/adda/DOMAIN_MODEL.md +16 -0
  18. adda-0.4.0/adda/MODULE_MAP.json +18 -0
  19. adda-0.4.0/adda/PROMPT_BASE/SYSTEM.md +14 -0
  20. adda-0.4.0/adda/STATE/CURRENT.md +15 -0
  21. adda-0.4.0/adda/STATE/checkpoints/20260826T070209Z.md +19 -0
  22. adda-0.4.0/adda/VERSION.md +7 -0
  23. adda-0.4.0/benchmarks/run.py +117 -0
  24. adda-0.4.0/docs/modules/README.md +35 -0
  25. adda-0.4.0/docs/modules/adda/audit.md +35 -0
  26. adda-0.4.0/docs/modules/adda/cli.md +48 -0
  27. adda-0.4.0/docs/modules/adda/compress.md +26 -0
  28. adda-0.4.0/docs/modules/adda/diff.md +34 -0
  29. adda-0.4.0/docs/modules/adda/evaluate.md +32 -0
  30. adda-0.4.0/docs/modules/adda/hook.md +36 -0
  31. adda-0.4.0/docs/modules/adda/modulemap.md +27 -0
  32. adda-0.4.0/docs/modules/adda/okf.md +27 -0
  33. adda-0.4.0/docs/modules/adda/rehydrate.md +32 -0
  34. adda-0.4.0/docs/modules/adda/sentinel.md +31 -0
  35. adda-0.4.0/docs/modules/adda/sync.md +35 -0
  36. adda-0.4.0/pyproject.toml +96 -0
  37. adda-0.4.0/scripts/check_counts.py +143 -0
  38. adda-0.4.0/scripts/smoke_test.py +82 -0
  39. adda-0.4.0/src/adda/__init__.py +5 -0
  40. adda-0.4.0/src/adda/audit.py +155 -0
  41. adda-0.4.0/src/adda/cli.py +454 -0
  42. adda-0.4.0/src/adda/compress.py +52 -0
  43. adda-0.4.0/src/adda/diff.py +55 -0
  44. adda-0.4.0/src/adda/evaluate.py +152 -0
  45. adda-0.4.0/src/adda/hook.py +85 -0
  46. adda-0.4.0/src/adda/modulemap.py +65 -0
  47. adda-0.4.0/src/adda/okf.py +194 -0
  48. adda-0.4.0/src/adda/rehydrate.py +24 -0
  49. adda-0.4.0/src/adda/sentinel.py +77 -0
  50. adda-0.4.0/src/adda/sync.py +261 -0
  51. adda-0.4.0/src/adda/templates/adda/API_CONTRACTS.md +9 -0
  52. adda-0.4.0/src/adda/templates/adda/ARCHITECTURE.md +22 -0
  53. adda-0.4.0/src/adda/templates/adda/DECISIONS/0001-record-architecture-decisions.md +17 -0
  54. adda-0.4.0/src/adda/templates/adda/DOMAIN_MODEL.md +10 -0
  55. adda-0.4.0/src/adda/templates/adda/PROMPT_BASE/SYSTEM.md +14 -0
  56. adda-0.4.0/src/adda/templates/adda/STATE/CURRENT.md +10 -0
  57. adda-0.4.0/src/adda/templates/adda/VERSION.md +10 -0
  58. adda-0.4.0/tests/test_audit.py +437 -0
  59. adda-0.4.0/tests/test_cli.py +62 -0
  60. adda-0.4.0/tests/test_compress.py +16 -0
  61. adda-0.4.0/tests/test_diff.py +67 -0
  62. adda-0.4.0/tests/test_eval.py +85 -0
  63. adda-0.4.0/tests/test_hook.py +160 -0
  64. adda-0.4.0/tests/test_modulemap.py +65 -0
  65. adda-0.4.0/tests/test_okf.py +73 -0
  66. adda-0.4.0/tests/test_rehydrate.py +33 -0
  67. adda-0.4.0/tests/test_sentinel.py +60 -0
  68. adda-0.4.0/tests/test_sync.py +298 -0
adda-0.4.0/.gitignore ADDED
@@ -0,0 +1,31 @@
1
+ # Developed by - Vedavyas Vayalpadu - vyas4c3@gmail.com
2
+ # Coded by - Claude Code
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ *.egg-info/
8
+ .eggs/
9
+ build/
10
+ dist/
11
+ *.egg
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # Test / tooling caches
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+
23
+ # ADDA's own generated OKF (regenerate with `adda export`)
24
+ okf.json
25
+
26
+ # OS noise
27
+ .DS_Store
28
+ Thumbs.db
29
+
30
+ # Claude Code local settings (machine-specific, never shared)
31
+ .claude/settings.local.json
adda-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vedavyas Vayalpadu
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.
@@ -0,0 +1,168 @@
1
+ <!-- Developed by - Vedavyas Vayalpadu - vyas4c3@gmail.com -->
2
+ <!-- Coded by - Claude Code -->
3
+
4
+ # OKF — Open Knowledge Format (v0.2)
5
+
6
+ OKF is a small, **provider-agnostic** JSON format that carries a software project's
7
+ architecture memory — version, constraints, modules, decisions, and state — in a
8
+ shape any LLM can consume. It is the centerpiece of ADDA: think "schema.org for
9
+ software-architecture context." ADDA (`src/adda/okf.py`) is its reference
10
+ implementation; this document is the locked spec for format version **0.2**.
11
+
12
+ `okf_version` is `"0.2"`. v0.2 adds `Module.path` (additive, optional) over v0.1.
13
+
14
+ ## Top-level fields
15
+
16
+ | Field | Type | Meaning |
17
+ |---|---|---|
18
+ | `okf_version` | string | OKF format version. `"0.2"`. |
19
+ | `project` | string | Project name. |
20
+ | `version` | string | Project version (the project's own, not OKF's). |
21
+ | `architecture` | object | See **Architecture** below. |
22
+ | `constraints` | string[] | Hard rules the LLM must never violate. |
23
+ | `decisions` | Decision[] | Architecture Decision Records (ADRs). |
24
+ | `state` | object | See **State** below. |
25
+
26
+ ### Architecture (object)
27
+
28
+ | Field | Type | Meaning |
29
+ |---|---|---|
30
+ | `overview` | string | One-paragraph prose overview (free text). |
31
+ | `modules` | Module[] | The system's components. |
32
+ | `domain_model` | string | Free-text domain entities/relationships. |
33
+ | `api_contracts` | string | Free-text public interfaces/routes/schemas. |
34
+
35
+ ### Module (object)
36
+
37
+ | Field | Type | Default | Meaning |
38
+ |---|---|---|---|
39
+ | `name` | string | — | Module identifier. |
40
+ | `description` | string | `""` | One-line description. |
41
+ | `status` | string | `"active"` | `active` \| `planned` \| `deprecated`. |
42
+ | `path` | string | `""` | Repo path this module maps to. Populated by `adda sync`; checked by `adda diff`. |
43
+
44
+ ### Decision (object)
45
+
46
+ | Field | Type | Default | Meaning |
47
+ |---|---|---|---|
48
+ | `id` | string | — | ADR id (e.g. `ADR-0001`). |
49
+ | `title` | string | `""` | Decision title. |
50
+ | `status` | string | `"accepted"` | `accepted` \| `proposed` \| `superseded` \| `rejected`. |
51
+
52
+ ### State (object)
53
+
54
+ | Field | Type | Meaning |
55
+ |---|---|---|
56
+ | `updated` | string | Last-updated marker (date or checkpoint id). |
57
+ | `summary` | string | One-line current-state summary. |
58
+
59
+ ## Active-item semantics (what `rehydrate` keeps)
60
+
61
+ The **minimal OKF** emitted by `adda rehydrate` (spec §13) keeps only:
62
+ `okf_version`, `project`, `version`, `constraints`, **active modules**
63
+ (`status == "active"`), and **active decisions** (`status` in `{accepted, active}`).
64
+ Everything else — `architecture.overview`, `domain_model`, `api_contracts`,
65
+ `state`, and any non-active items — is dropped to minimize the payload.
66
+
67
+ ## Where each field comes from (`/adda` → OKF)
68
+
69
+ | `/adda` file | OKF target |
70
+ |---|---|
71
+ | `VERSION.md` (`project:` / `version:` lines) | `project`, `version` |
72
+ | `ARCHITECTURE.md` overview paragraph | `architecture.overview` |
73
+ | `ARCHITECTURE.md` `## Constraints` bullets | `constraints` |
74
+ | `ARCHITECTURE.md` `## Modules` bullets | `architecture.modules` |
75
+ | `DOMAIN_MODEL.md` body | `architecture.domain_model` |
76
+ | `API_CONTRACTS.md` body | `architecture.api_contracts` |
77
+ | `DECISIONS/*.md` (`id:` / `status:` / H1) | `decisions` |
78
+ | `STATE/CURRENT.md` (`updated:` / `summary:`) | `state` |
79
+
80
+ **Module line syntax:** `- name: description (status) [path]` — `(status)` and
81
+ `[path]` are optional and stripped from the right; the remainder splits on the
82
+ first `:` into name/description.
83
+
84
+ ## Example
85
+
86
+ ```json
87
+ {
88
+ "okf_version": "0.2",
89
+ "project": "My Project",
90
+ "version": "0.1.0",
91
+ "architecture": {
92
+ "overview": "",
93
+ "modules": [
94
+ { "name": "core", "description": "Core domain logic.", "status": "active", "path": "src/core" }
95
+ ],
96
+ "domain_model": "",
97
+ "api_contracts": ""
98
+ },
99
+ "constraints": ["Keep architecture docs in /adda up to date before changing code."],
100
+ "decisions": [
101
+ { "id": "ADR-0001", "title": "Keep decisions in /adda", "status": "accepted" }
102
+ ],
103
+ "state": { "updated": "2026-06-25", "summary": "Scaffolded." }
104
+ }
105
+ ```
106
+
107
+ ## Canonical JSON Schema
108
+
109
+ Generated from the pydantic models in `src/adda/okf.py` via
110
+ `OKF.model_json_schema()` — this file stays the documentation; the code stays the
111
+ source of truth.
112
+
113
+ ```json
114
+ {
115
+ "$defs": {
116
+ "Architecture": {
117
+ "properties": {
118
+ "overview": { "default": "", "title": "Overview", "type": "string" },
119
+ "modules": { "items": { "$ref": "#/$defs/Module" }, "title": "Modules", "type": "array" },
120
+ "domain_model": { "default": "", "title": "Domain Model", "type": "string" },
121
+ "api_contracts": { "default": "", "title": "Api Contracts", "type": "string" }
122
+ },
123
+ "title": "Architecture",
124
+ "type": "object"
125
+ },
126
+ "Decision": {
127
+ "properties": {
128
+ "id": { "title": "Id", "type": "string" },
129
+ "title": { "default": "", "title": "Title", "type": "string" },
130
+ "status": { "default": "accepted", "title": "Status", "type": "string" }
131
+ },
132
+ "required": ["id"],
133
+ "title": "Decision",
134
+ "type": "object"
135
+ },
136
+ "Module": {
137
+ "properties": {
138
+ "name": { "title": "Name", "type": "string" },
139
+ "description": { "default": "", "title": "Description", "type": "string" },
140
+ "status": { "default": "active", "title": "Status", "type": "string" },
141
+ "path": { "default": "", "title": "Path", "type": "string" }
142
+ },
143
+ "required": ["name"],
144
+ "title": "Module",
145
+ "type": "object"
146
+ },
147
+ "State": {
148
+ "properties": {
149
+ "updated": { "default": "", "title": "Updated", "type": "string" },
150
+ "summary": { "default": "", "title": "Summary", "type": "string" }
151
+ },
152
+ "title": "State",
153
+ "type": "object"
154
+ }
155
+ },
156
+ "properties": {
157
+ "okf_version": { "default": "0.2", "title": "Okf Version", "type": "string" },
158
+ "project": { "default": "", "title": "Project", "type": "string" },
159
+ "version": { "default": "", "title": "Version", "type": "string" },
160
+ "architecture": { "$ref": "#/$defs/Architecture" },
161
+ "constraints": { "items": { "type": "string" }, "title": "Constraints", "type": "array" },
162
+ "decisions": { "items": { "$ref": "#/$defs/Decision" }, "title": "Decisions", "type": "array" },
163
+ "state": { "$ref": "#/$defs/State" }
164
+ },
165
+ "title": "OKF",
166
+ "type": "object"
167
+ }
168
+ ```
adda-0.4.0/PKG-INFO ADDED
@@ -0,0 +1,349 @@
1
+ Metadata-Version: 2.5
2
+ Name: adda
3
+ Version: 0.4.0
4
+ Summary: ADDA — anti-drift architecture memory + OKF + Context Sentinel for AI-assisted development.
5
+ Project-URL: Homepage, https://github.com/vyasdx/adda-cli
6
+ Project-URL: Repository, https://github.com/vyasdx/adda-cli
7
+ Project-URL: Issues, https://github.com/vyasdx/adda-cli/issues
8
+ Author-email: Vedavyas Vayalpadu <vyas4c3@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,anti-drift,architecture,context,llm,okf
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Documentation
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: pydantic>=2
21
+ Requires-Dist: typer>=0.12
22
+ Provides-Extra: all
23
+ Requires-Dist: anthropic>=0.39; extra == 'all'
24
+ Requires-Dist: headroom-ai; extra == 'all'
25
+ Requires-Dist: pytest>=8; extra == 'all'
26
+ Provides-Extra: anthropic
27
+ Requires-Dist: anthropic>=0.39; extra == 'anthropic'
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Provides-Extra: headroom
31
+ Requires-Dist: headroom-ai; extra == 'headroom'
32
+ Description-Content-Type: text/markdown
33
+
34
+ <!-- Developed by - Vedavyas Vayalpadu - vyas4c3@gmail.com -->
35
+ <!-- Coded by - Claude Code -->
36
+
37
+ <p align="center">
38
+ <img src="assets/logo.png" alt="ADDA — a hooded sentinel guarding memory, with the adda wordmark and the tagline Drift Breaker Mode" width="520">
39
+ </p>
40
+
41
+ <p align="center">
42
+ <i>Your AI forgets your architecture. ADDA remembers it for them.</i>
43
+ </p>
44
+
45
+ <p align="center">
46
+ <sub>Compression shrinks the pipe. ADDA breaks the drift.</sub>
47
+ </p>
48
+
49
+ <p align="center">
50
+ <img alt="version 0.4.0" src="https://img.shields.io/badge/version-0.4.0-1d9e75">
51
+ <img alt="python 3.10+" src="https://img.shields.io/badge/python-3.10%2B-185fa5">
52
+ <img alt="tests 84 passing" src="https://img.shields.io/badge/tests-84%20passing-3b6d11">
53
+ <img alt="OKF v0.2" src="https://img.shields.io/badge/OKF-v0.2-534ab7">
54
+ <img alt="provider-agnostic" src="https://img.shields.io/badge/LLM-provider--agnostic-0f6e56">
55
+ </p>
56
+
57
+ ---
58
+
59
+ **ADDA** (Anti-Drift Documentation Architecture) finds documentation that has
60
+ quietly stopped being true — and tells you what it could not determine.
61
+
62
+ Missing documentation is visible. Drifted documentation is not: it was true when
63
+ written, the code moved, and the file still reads as authoritative. Agents make
64
+ this worse in both directions — they generate documentation readily, and they
65
+ have no mechanism to notice when what they wrote stopped being true.
66
+
67
+ ## Two minutes, on a repo you already have
68
+
69
+ No setup, no authored documents, nothing to fill in first:
70
+
71
+ ```bash
72
+ pip install adda
73
+
74
+ cd /your/project
75
+ adda sync . --map --out adda/MODULE_MAP.json # route each code path to its doc
76
+ adda audit . # what has drifted?
77
+ ```
78
+
79
+ ```
80
+ Doc drift detected: 2 finding(s)
81
+ [high ] doc missing docs/modules/auth/session.md
82
+ [high ] doc missing docs/modules/billing/limiter.md
83
+ ```
84
+
85
+ Write those docs, commit, and `audit` goes quiet. Change the code without
86
+ touching its doc, and it comes back:
87
+
88
+ ```
89
+ Doc drift detected: 1 finding(s)
90
+ [medium] doc stale docs/modules/billing/limiter.md
91
+ ```
92
+
93
+ It exits non-zero when it finds something, so it drops straight into CI. Make it
94
+ a commit gate with `adda hook install`.
95
+
96
+ **It reports what it cannot determine.** Staleness comes from git commit
97
+ ancestry, not a hand-written date — and when two commits are unordered
98
+ (divergent branches, a rebase, a shallow clone) the answer is *"cannot tell"*,
99
+ reported as a skip rather than a pass. A green check that was structurally blind
100
+ is worse than no check.
101
+
102
+ ## The other half: architecture memory
103
+
104
+ If you want your assistant to *remember* the architecture as well as keep its
105
+ docs honest, ADDA is also:
106
+
107
+ - **ADDA memory** — constraints, modules, decisions and state as markdown in `/adda`, versioned in git. You author it; that is the point.
108
+ - **OKF** — compiles that memory to small, provider-agnostic JSON any LLM can read.
109
+ - **Context Sentinel** — a token gauge that says *when* to checkpoint, before a compaction wipes your context.
110
+
111
+ `adda init` scaffolds that layout. It is a bigger commitment than the drift
112
+ checks above, and entirely optional — `sync`, `audit` and `hook` never read it.
113
+
114
+ ## Where ADDA fits
115
+
116
+ A whole class of tools **compresses** what flows to the model — shrinking tool
117
+ outputs, file reads, and JSON in the pipe (e.g. [headroom-ai](https://github.com/chopratejas/headroom),
118
+ which ADDA wires in optionally). But compression fights the provider's prefix cache
119
+ for the *same tokens*, and on cache-heavy agent traffic the cache usually wins —
120
+ real-world code reviews land ~4%. ADDA works one layer up: not the bytes in any single
121
+ request, but the **persistent, versioned memory** of your architecture across
122
+ sessions — a different axis, with no cache to collide with.
123
+
124
+ That layer is exactly where **drift** lives — and it's the gap compression layers
125
+ don't close. ADDA owns it: `adda diff` measures when code has drifted from the docs,
126
+ `adda audit` sweeps the whole repo for doc-layer drift the moment it happens, `adda
127
+ hook` blocks a commit that introduces it, and `adda eval` measures how much memory
128
+ survives a rehydration. ADDA doesn't just **detect** drift — it **enforces** against
129
+ it at commit time. Compress the pipe *and* anchor the memory — they stack.
130
+
131
+ ## Before / after
132
+
133
+ **Before** — you hit `/compact` without a handover:
134
+
135
+ ```text
136
+ You: continue implementing the payment flow
137
+ Model: sure — I'll add a new PaymentService and a fresh DB table...
138
+ (it forgot ADR-0007: "all money lives in the ledger, never a new table")
139
+ You: no. we decided that months ago. it's in the ledger.
140
+ (you spend the next hour re-explaining your own architecture)
141
+ ```
142
+
143
+ **After** — `adda rehydrate` restores the memory first:
144
+
145
+ ```bash
146
+ adda rehydrate . | your-llm # minimal OKF: version + constraints + active ADRs + active modules
147
+ # memory restored in seconds, ~47% fewer tokens than the full export
148
+ ```
149
+
150
+ ## 1. Why not just Claude's native Compaction?
151
+
152
+ Claude 4.x ships built-in **Compaction** that summarizes earlier context server-side
153
+ as you approach the window. So why ADDA?
154
+
155
+ Native compaction is **single-session, single-provider, and opaque**: it lives inside
156
+ one conversation, runs only on Claude, and you cannot see, edit, or version what it
157
+ chose to keep or drop.
158
+
159
+ | | Native Compaction | ADDA |
160
+ |---|---|---|
161
+ | Scope | One conversation | Cross-session — memory lives in git, survives `/clear`, new chats, new machines |
162
+ | Provider | Claude only | Cross-LLM — OKF is provider-agnostic JSON; feeds Claude, Codex, anything |
163
+ | Transparency | Opaque server summary | Inspectable, editable markdown → JSON |
164
+ | History | None | Git-versioned — every constraint/ADR/module change is a reviewable diff |
165
+ | Drift | Cannot detect | `adda diff` flags where code diverged from the docs |
166
+ | Measurable | No | `adda eval` scores how much memory survives rehydration |
167
+
168
+ ADDA doesn't compete with Compaction — it can **feed** it: `adda rehydrate` emits a
169
+ curated minimal OKF you inject into the model (or into a compaction prompt), so the
170
+ session starts from your source-of-truth architecture instead of a lossy auto-summary.
171
+
172
+ ## The closed loop
173
+
174
+ ```
175
+ adda monitor → warns at 60% context → adda checkpoint (snapshot state)
176
+ ↑ ↓
177
+ adda rehydrate ← (compact happens, memory lost) ←
178
+ ```
179
+
180
+ Monitor → checkpoint → compact → rehydrate. A self-correcting loop against drift.
181
+ The north-star is **`adda rehydrate`**: after a compaction, emit the *minimal* OKF to
182
+ instantly restore the LLM's architectural memory. A second loop runs alongside it at
183
+ commit time: **`adda hook`** blocks a commit that stages code without its doc, and
184
+ **`adda audit`** catches whatever the hook didn't (pre-existing drift, files that
185
+ predate the gate) on the next repo-wide sweep — detection and enforcement, not
186
+ detection alone. It also prints, under `[skipped]`, every source root discovery
187
+ chose not to map and why; add that root to `"include"` in `MODULE_MAP.json` to
188
+ pull it back under enforcement.
189
+
190
+ ## Install
191
+
192
+ ```bash
193
+ pip install adda
194
+ pip install "adda[headroom]" # optional compression (heavy; not required)
195
+ ```
196
+
197
+ From a clone instead, for development:
198
+
199
+ ```bash
200
+ pip install -e ".[dev]"
201
+ ```
202
+
203
+ Installs the `adda` console script.
204
+
205
+
206
+ **CI.** `.github/workflows/ci.yml` runs the tests plus `adda diff`, `adda audit` and a `adda eval` assertion that load-bearing fidelity stays at 100%, on Python 3.10 and 3.13. It checks out with `fetch-depth: 0` because `audit` decides staleness from git ancestry and a shallow clone cannot answer that.
207
+
208
+ ## Commands
209
+
210
+ **Core loop:**
211
+
212
+ ```bash
213
+ adda init ./my-project # scaffold the /adda layout
214
+ adda export ./my-project --okf # /adda/*.md -> validated okf.json
215
+ adda monitor --tokens 130000 --limit 200000 # 65% -> CHECKPOINT
216
+ adda rehydrate ./my-project # minimal OKF (pipe into your LLM)
217
+ adda checkpoint ./my-project -m "before compact"
218
+ ```
219
+
220
+ **Drift breakers:**
221
+
222
+ ```bash
223
+ adda sync ./my-project # derive an ARCHITECTURE skeleton (modules + deps) from the code
224
+ adda sync ./my-project --map # derive MODULE_MAP.json (code -> doc routing) instead
225
+ adda diff ./my-project # detect drift: docs vs actual repo (exit 1 on drift)
226
+ adda eval ./my-project # rehydration fidelity %
227
+ ```
228
+
229
+ **Enforcement (v0.3):**
230
+
231
+ ```bash
232
+ adda audit ./my-project # repo-wide doc-layer drift sweep: missing/stale/unmapped/orphaned docs
233
+ adda hook install ./my-project # install a pre-commit gate: blocks staging code without its doc
234
+ adda hook run ./my-project # what the installed hook invokes (staged-vs-staged, no dates, no LLM)
235
+ ```
236
+
237
+ `adda init` writes the spec layout: `VERSION.md`, `ARCHITECTURE.md`, `DOMAIN_MODEL.md`,
238
+ `API_CONTRACTS.md`, `DECISIONS/`, `STATE/`, `PROMPT_BASE/`. Edit the markdown, then
239
+ `adda export` compiles it to `okf.json`. `audit` reads `MODULE_MAP.json` (from `adda
240
+ sync --map`) to know which doc each code path owes; `hook install` is what makes the
241
+ gate run automatically, not only when someone remembers to type `adda audit`.
242
+
243
+ ## Numbers
244
+
245
+ Measured 2026-08-26 by `benchmarks/run.py` against real repositories ADDA did not
246
+ design. Reproduce with:
247
+
248
+ ```bash
249
+ python benchmarks/run.py . ../flask ../requests ../fastapi ../django ../date-fns
250
+ ```
251
+
252
+ | repo | commit | modules | mapped | exempt | skipped | collisions | time | load-bearing | overall | payload cut |
253
+ |---|---|---|---|---|---|---|---|---|---|---|
254
+ | ADDA | `v0.4.0` | 1 | 11 | 1 | 0 | 0 | 0.01s | **100.0%** | 87.5% | 46.9% |
255
+ | flask | `d318b68` | 1 | 21 | 3 | 0 | 0 | 0.01s | n/a | n/a | n/a |
256
+ | requests | `5460f46` | 1 | 18 | 1 | 0 | 0 | 0.01s | n/a | n/a | n/a |
257
+ | fastapi | `9a8a13f` | 2 | 41 | 7 | 458 (`docs_src`) | 0 | 0.26s | n/a | n/a | n/a |
258
+ | django | `0b40210` | 3 | 719 | 199 | 0 | 0 | 2.18s | n/a | n/a | n/a |
259
+ | date-fns | `a0a3922` | 2 | 1256 | 0 | 0 | 0 | 1.33s | n/a | n/a | n/a |
260
+
261
+ Commit SHAs are recorded because otherwise the table is reproducible mechanically
262
+ but not in time — running it next month benchmarks different code. That applies
263
+ to ADDA's own row too: its fidelity and payload figures move as its architecture
264
+ memory grows, so they describe this repo at that point rather than a fixed
265
+ property of the tool. Its row is pinned to a release tag rather than a commit
266
+ for that reason — a tag is a thing you can check out and reproduce.
267
+
268
+ **Zero collisions across 2,066 mapped files.** That number is the point: a doc path
269
+ that two code paths share is a module reported as documented while having no
270
+ documentation, and the mapping is derived so that cannot happen.
271
+
272
+ **The `skipped` column is the other half, and it is deliberately in the table.**
273
+ `audit` can only report drift in code that discovery mapped, so a root it never
274
+ reaches is reported as clean rather than as unexamined. fastapi's `docs_src/` is
275
+ 458 tutorial snippets in a directory with no `__init__.py`; mapping them would
276
+ bury every real finding, so ADDA skips them — and says so, in `audit` output and
277
+ here, instead of quietly showing 41. Overrule it per root with `"include"` in
278
+ `MODULE_MAP.json` (ADR-0009).
279
+
280
+ **Why fidelity is `n/a` for most rows, and not filled in.** Rehydration fidelity
281
+ scores how much *authored* architecture memory survives `rehydrate`. Real
282
+ repositories have none — running `adda init` first would score an empty scaffold,
283
+ which measures the template rather than the tool. So it is reported only where real
284
+ `/adda` memory exists.
285
+
286
+ Where it can be measured, load-bearing fidelity is **100%**: `rehydrate` loses none
287
+ of the constraints, active modules or in-force decisions while cutting the payload
288
+ roughly in half. Overall fidelity sits below 100% by design — dropping prose and
289
+ inactive items is the compression trade-off.
290
+
291
+ ## OKF — the format
292
+
293
+ OKF is the wedge: a small, provider-agnostic JSON format for software-architecture
294
+ context ("schema.org for architecture context"). The locked schema (v0.2) is documented
295
+ in **[OKF_SCHEMA.md](OKF_SCHEMA.md)**, with ADDA as its reference implementation. The
296
+ same JSON feeds any LLM; `adda rehydrate` is the integration surface a future MCP server
297
+ or editor skill can expose without changing the format.
298
+
299
+ ## What staleness detection cannot see
300
+
301
+ Worth stating plainly, because it is the boundary of the technique rather than a
302
+ bug queued for a future release.
303
+
304
+ `audit` decides a doc is stale by **git commit ancestry**: if the code's last
305
+ commit is a descendant of the doc's last commit, the doc was written first and
306
+ has not been touched since. That is a reliable answer to one question — *was
307
+ this doc left behind?*
308
+
309
+ It cannot answer a different one: **was this doc updated, but updated wrongly?**
310
+
311
+ We hit exactly that here. Two module docs contradicted themselves one day after
312
+ being written: one described a function that had been deleted in the same
313
+ commit, the other listed a public surface that no longer matched. Both were
314
+ committed alongside the code they describe, so ancestry called them current, the
315
+ commit gate passed, `audit` passed, and CI was green. A human reviewer found
316
+ them.
317
+
318
+ So: **ADDA detects the doc nobody touched. It does not detect the doc someone
319
+ touched carelessly.** The first is the common failure and is worth automating.
320
+ The second still needs review, and no ancestry check will ever catch it.
321
+
322
+ Two related boundaries, for completeness:
323
+
324
+ - **Ancestry can be undecidable**, on a shallow clone or after a rebase. ADDA
325
+ reports those under `[skipped]` rather than counting them as fresh — a check
326
+ that cannot answer says so.
327
+ - **Discovery reports what it *chose* to skip, not what it never reached.** A
328
+ root the heuristic drops is printed; see the `skipped` column above.
329
+
330
+ ## Limitations
331
+
332
+ Honest about what it does and doesn't do:
333
+
334
+ - **You still curate.** `adda sync` derives a skeleton from the code, but the constraints, decisions, and prose are yours to write — ADDA won't invent them.
335
+ - **`adda diff` matches modules by path/name.** Rename a module without updating its `[path]` and it shows as drift (by design — that *is* drift you should reconcile).
336
+ - **`adda eval` is a deterministic content metric**, not an LLM-judged score. It measures which architecture facts survive rehydration, offline and reproducibly — it does not call a model (ADDA is a context tool, not an LLM executor).
337
+ - **`--compress` (headroom-ai) is lossy *as ADDA uses it*, and opt-in.** ADDA calls Headroom's library `compress()`, which drops low-signal content. Headroom compression is *reversible* when you run its proxy + MCP retrieve tool (the model can fetch the original back) — ADDA doesn't wire that path, so it keeps `--compress` off by default and always emits faithful, valid OKF.
338
+ - **Memory is local git.** No server/MCP yet — that's a deliberate future surface, not built in.
339
+
340
+ ## Smoke test & development
341
+
342
+ ```bash
343
+ python scripts/smoke_test.py # runs the whole closed loop in a temp dir
344
+ pip install -e ".[dev]" && pytest -q
345
+ ```
346
+
347
+ ---
348
+
349
+ Developed by - Vedavyas Vayalpadu - vyas4c3@gmail.com · Coded by - Claude Code