charter-intent 0.4.2__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Charter contributors
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,5 @@
1
+ recursive-include demo *
2
+ recursive-include tests *.py
3
+ prune demo/repo
4
+ global-exclude __pycache__
5
+ global-exclude *.py[cod]
@@ -0,0 +1,312 @@
1
+ Metadata-Version: 2.4
2
+ Name: charter-intent
3
+ Version: 0.4.2
4
+ Summary: Executable design intent for AI-coded repos: the design document becomes the charter.
5
+ Author: cspergel
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/cspergel/Charter
8
+ Project-URL: Issues, https://github.com/cspergel/Charter/issues
9
+ Project-URL: Changelog, https://github.com/cspergel/Charter/blob/main/CHANGELOG.md
10
+ Keywords: ai-agents,governance,adr,traceability,claude-code,intent
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Dynamic: license-file
25
+
26
+ # charter — the design document becomes the charter
27
+
28
+ Your design doc says:
29
+
30
+ > Auth tokens are HMAC, never JWT.
31
+
32
+ ```bash
33
+ $ charter annotate SPEC.md # LLM turns prose into enforceable decisions
34
+ $ cat CHARTER.md
35
+ [D-001] Auth tokens are HMAC, never JWT -> assert: ! grep -rqE "jwt|jsonwebtoken" src
36
+ $ charter approve --why "initial review"
37
+ ```
38
+
39
+ Weeks later, an AI agent adds JWT code.
40
+
41
+ ```bash
42
+ $ charter check
43
+ FAIL D-001 "Auth tokens are HMAC, never JWT" — assert FAILED
44
+ ```
45
+
46
+ The agent fixes it. Nobody was interrupted, nothing was forgotten, and
47
+ `charter trace D-001` shows every file that implements the decision.
48
+
49
+ That's the whole idea: **executable design intent for AI-coded repos** —
50
+ ADRs + linter + traceability, in one file with almost no state.
51
+
52
+ The doctrine in one sentence: **a decision with no jurisdiction is not
53
+ governed.** Every decision names an enforcer; a supervise-only decision with
54
+ neither code citations nor an `@` watch scope fails check. CHARTER.md is the
55
+ constitution, `check` is the court, `audit` is the judge for gray areas, and
56
+ `[D-xxx]` citations are the map.
57
+
58
+ Try it in 30 seconds: `sh demo/run_demo.sh` (on Windows, run it from Git
59
+ Bash) — an agent adds Supabase to a local-first app and check catches it.
60
+ No API key needed.
61
+
62
+ ## Quick start
63
+
64
+ See it work first — the demo is offline and needs no API key (on Windows,
65
+ run it from Git Bash):
66
+
67
+ ```bash
68
+ git clone https://github.com/cspergel/Charter
69
+ cd Charter
70
+ sh demo/run_demo.sh # an agent adds Supabase to a local-first app; check catches it
71
+ ```
72
+
73
+ Then use it on your own repo. There are two ways to run it:
74
+
75
+ ```bash
76
+ # Option A — zero install. It's one file, zero dependencies (Python 3.10+).
77
+ python /path/to/charter.py check
78
+
79
+ # Option B — install the `charter` command.
80
+ pip install charter-intent # the command is `charter`; `charter` was taken on PyPI
81
+ # — or from a local checkout: pip install .
82
+ charter check
83
+ ```
84
+
85
+ `annotate` (turning a prose doc into decisions) needs an LLM backend; point it
86
+ at Claude Code with no API key required:
87
+
88
+ ```bash
89
+ export CHARTER_LLM_CMD="claude -p" # or set ANTHROPIC_API_KEY
90
+ charter annotate SPEC.md
91
+ charter approve --why "initial review"
92
+ charter check
93
+ charter doctor # checks your setup is sound
94
+ ```
95
+
96
+ State on disk: `CHARTER.md` (yours), `.charter/ledger.jsonl` (append-only
97
+ journal), and `.charter/charter.sha` (approval hash — commit it). Permission to
98
+ *execute* asserts is recorded in a per-user trust store **outside** the repo
99
+ (`~/.charter/trust`, keyed by repo path), so nothing a repo ships can grant
100
+ itself execution.
101
+
102
+ ## Security, in one paragraph
103
+
104
+ `charter check` executes shell commands defined in CHARTER.md (the assert
105
+ enforcers). A freshly cloned repo will **not** execute its asserts — even if it
106
+ ships an approval hash, and even if it ships a forged trust marker — until you
107
+ review CHARTER.md and run `charter approve` yourself, because the trust record
108
+ lives in a per-user store outside the repo. CI opts in explicitly with
109
+ `CHARTER_TRUST_ASSERTS=1`. `annotate`/`audit` send doc and file contents to
110
+ your configured LLM backend; nothing else makes network calls. Details and
111
+ threat model: [SECURITY.md](SECURITY.md).
112
+
113
+ ## The lifecycle
114
+
115
+ ```
116
+ charter annotate SPEC.md # LLM reads your prose doc, extracts binding
117
+ # decisions, assigns [D-xxx] symbols, proposes
118
+ # the lowest viable enforcer per decision,
119
+ # writes CHARTER.md + SPEC.annotated.md
120
+ # (charter init creates an empty CHARTER.md
121
+ # if you'd rather write it by hand)
122
+ <review CHARTER.md once> # the only mandatory human moment: adjust
123
+ # enforcers, strengthen supervise items
124
+ charter approve --why "..." # the human gate: journaled, hash-stamped
125
+ charter check # deterministic, free — pre-commit + CI
126
+ charter audit # judged pass over supervise-tier (PR-time)
127
+ charter digest [--mark] # batch-review everything the system did
128
+ charter trace D-001 # everything that traces to a decision
129
+ charter graph [--json] # the derived graph (Mermaid / machine-readable)
130
+ charter explain D-001 # the full story of one decision
131
+ charter doctor # setup-health checks
132
+ charter install-hook # pre-commit hook + Claude Code settings block
133
+ ```
134
+
135
+ ## The line syntax
136
+
137
+ ```
138
+ [D-001] title -> assert: <must-pass> !! <proof-must-succeed> @ glob, glob
139
+ [D-002] title -> supervise @ src/db/**
140
+ ```
141
+
142
+ - The enforcer kind is one of the ladder below.
143
+ - `!!` introduces an assert's **tripwire**: a probe that must succeed,
144
+ proving the detector can detect a known violation sample (a typo'd grep
145
+ path can't pass forever). The canonical pattern is
146
+ `echo <violation-sample> | <the-real-detector>`.
147
+ - `@` declares **watch scope**: a human-set jurisdiction floor. Audit reads
148
+ cited files ∪ watched files, so an uncited violating file is still seen.
149
+
150
+ ## The five layers
151
+
152
+ 1. **Annotate** — the bootstrap agent. Extraction is conservative
153
+ (contracts, not preferences — "keep the code simple" is correctly
154
+ ignored), capped at 15 by default (`--cap N`), dedupes against decisions
155
+ already indexed, and annotation of your original doc is non-destructive
156
+ (writes a `.annotated` copy with symbols inlined at the source sentences).
157
+ 2. **Enforce** — the ladder, strongest first: `structure > type > test >
158
+ lint > assert > supervise`. During review, push supervise items toward
159
+ the stronger deterministic rungs. `check` fails on: aspirational
160
+ decisions (no enforcer), missing enforcer targets, **enforcer rot** (the
161
+ `#Symbol` vanished in a refactor), failing asserts, and **blind
162
+ decisions** (supervise-only with no citations and no watch scope). A
163
+ proposed enforcer that doesn't exist yet is a **build obligation** —
164
+ check stays red until the builder creates the type/test, which is
165
+ governance generating the skeleton of the system. `check --budget N`
166
+ warns when judgment-only decisions outgrow the budget (default 5).
167
+ 3. **Trace** — builders leave `[D-xxx]` citations in comments and commits.
168
+ The graph is **derived from grep on every run, never stored** — so it can
169
+ never go stale.
170
+ 4. **Supervise** — `audit` judges only the supervise tier, and **citations
171
+ are the scope**: the auditor reads exactly the files that claim to
172
+ implement the decision, plus watched files. Verdicts: COMPLIES (ok line,
173
+ exit 0), VIOLATES (exit 1 — fix the code), AMBIGUOUS (flagged for digest
174
+ review). All verdicts land in the ledger. No backend configured →
175
+ everything AMBIGUOUS, never crashes.
176
+ 5. **Steer** — one optional SessionStart hook injects the whole index
177
+ (~15 one-liners, a few hundred tokens, once per session) plus the
178
+ citation protocol. No gates: agents stay in their native loop — cite the
179
+ symbol, keep `check` green.
180
+
181
+ ## LLM backends
182
+
183
+ Resolution order for `annotate` and `audit`:
184
+
185
+ 1. `CHARTER_LLM_CMD` — any command that reads the prompt on stdin and
186
+ prints the reply on stdout. Point it at Claude Code headless:
187
+ `export CHARTER_LLM_CMD="claude -p"` — rides your existing plan.
188
+ 2. `ANTHROPIC_API_KEY` — direct API (Sonnet for annotation quality, Haiku
189
+ for cheap audit verdicts; override with `CHARTER_ANNOTATE_MODEL` /
190
+ `CHARTER_AUDIT_MODEL`).
191
+ 3. Neither — `annotate` explains itself; `audit` degrades to AMBIGUOUS.
192
+
193
+ ## Integration
194
+
195
+ `.git/hooks/pre-commit` (or just run `charter install-hook`):
196
+ ```bash
197
+ python charter.py check || exit 1
198
+ ```
199
+
200
+ CI on PRs (the judged layer) — note the explicit opt-in, and treat PRs that
201
+ modify CHARTER.md like PRs that modify your CI workflows:
202
+ ```bash
203
+ CHARTER_TRUST_ASSERTS=1 python charter.py check && python charter.py audit
204
+ ```
205
+
206
+ `.claude/settings.json` (optional steering):
207
+ ```json
208
+ {
209
+ "hooks": {
210
+ "SessionStart": [
211
+ { "hooks": [ { "type": "command", "command": "python charter.py hook" } ] }
212
+ ]
213
+ }
214
+ }
215
+ ```
216
+
217
+ For non-hook agents (Cursor, aider), put this in `AGENTS.md`/`.cursorrules`:
218
+
219
+ > This repo's binding decisions live in CHARTER.md. When your work implements
220
+ > or touches a decision, leave its `[D-xxx]` symbol in a nearby comment and
221
+ > your commit message. Run `python charter.py check` before finishing; a
222
+ > failure means an enforcer caught a violation — fix the code, never the
223
+ > enforcer. Conflicts between a request and a decision must be surfaced, not
224
+ > silently resolved.
225
+
226
+ ## Liberties taken, and why
227
+
228
+ - **Citations replace scope globs.** The derived graph defines what each
229
+ decision governs. This deleted the lockfile, ack protocol, session
230
+ baselines, and per-edit hooks of earlier designs — the single largest
231
+ overhead reduction — at the cost of relying on builders to cite. The
232
+ steering hook + agent instructions make citing the path of least
233
+ resistance, and `check` fails supervise decisions that end up blind.
234
+ - **Stateless judgment.** `audit` judges *current* state, not drift-since —
235
+ so there is nothing to pin, ack, or reconcile. Run it whenever; the ledger
236
+ is the only memory, and it's append-only and reviewable.
237
+ - **The graph navigates; enforcers govern.** `graph --json` exists for
238
+ agents to ask "what connects to what," but no verdict ever comes from
239
+ graph topology — authority lives in things that can't be argued with.
240
+
241
+ ## FAQ
242
+
243
+ **Isn't this just a pre-commit hook that runs grep?**
244
+ At the deterministic layer, yes — and that's the point. A grep that can't be
245
+ argued with beats an LLM that can be talked out of a verdict. Charter's value
246
+ isn't a cleverer check; it's turning prose decisions into checks at all,
247
+ keeping them in sync with the code via citations, and proving the checks aren't
248
+ vacuous (tripwires). The grep is a feature, not an embarrassment.
249
+
250
+ **Why not Spec Kit / OpenSpec / Kiro?**
251
+ Those govern code *generation* — write a spec, then generate from it. They're
252
+ out of the loop the moment a later change quietly contradicts the original
253
+ design, which is where drift actually accrues. Charter governs the repo from
254
+ then on, on every commit. They compose: scaffold with whatever you like, keep
255
+ it true with Charter.
256
+
257
+ **An LLM wrote my enforcement rules — why would I trust that?**
258
+ You don't trust it — you review it. `annotate` only *proposes*; nothing takes
259
+ effect until you read CHARTER.md and `approve` it, exactly like reading code
260
+ you're about to run. At enforcement time there's no LLM in the loop: `check` is
261
+ deterministic shell. The model proposes, you ratify, grep decides.
262
+
263
+ **What stops an agent from editing CHARTER.md, or weakening an enforcer, to make
264
+ check pass?**
265
+ Any change to CHARTER.md fails `check` until a human runs `approve` (a hashed,
266
+ journaled gate) — so an agent can't quietly rewrite the constitution. The agent
267
+ instructions say *fix the code, never the enforcer*, and a weakened assert trips
268
+ its tripwire (the proof that it can still catch a known violation). Tampering is
269
+ visible, not silent.
270
+
271
+ **Won't grep-based asserts be brittle and false-positive?**
272
+ Some will — which is why the ladder exists. Push fragile checks up to `type`,
273
+ `test`, or `lint`, where the language and your test runner do the work; reserve
274
+ `assert` for things that genuinely are a grep. Tripwires flag asserts that have
275
+ quietly stopped detecting anything, so a brittle check fails loudly rather than
276
+ passing forever.
277
+
278
+ **Does it lock me into Claude?**
279
+ No. Any backend that reads a prompt on stdin works (`CHARTER_LLM_CMD`), the
280
+ Anthropic API works, and you can skip the LLM entirely and write CHARTER.md by
281
+ hand — `check` never calls a model.
282
+
283
+ ## Known limits
284
+
285
+ - **`check` executes shell from CHARTER.md.** The trust gate means a cloned
286
+ repo can't run code on your machine before you review it, but after you
287
+ approve, the asserts are exactly as trustworthy as your review of them.
288
+ Read them like code you are about to run — because they are.
289
+ - A builder that never cites makes citation-only supervise decisions blind —
290
+ check fails them rather than letting them silently un-govern. Decisions
291
+ with `@` watch globs are still audited via watched files. Deterministic
292
+ rungs are immune — prefer them.
293
+ - Annotation quality is bounded by the doc: vague prose yields supervise
294
+ proposals. The review-once step is where you strengthen enforcers.
295
+ - `assert` commands are POSIX-shell; on Windows they run under Git Bash
296
+ (auto-detected, `CHARTER_SHELL` overrides).
297
+ - A vacuous assert's `!! proof` is authored by the same source as the
298
+ assert, so the tripwire raises the bar but can't fully self-police —
299
+ `check` flags trivially-true probes (`!! true`, bare `echo`), but a
300
+ cleverly matched fake proof still needs the human review-once gate.
301
+ - `audit` judges at most the first 60 in-scope files per decision (chunked,
302
+ worst-verdict-wins) to bound LLM cost; broad `@ src/**` scopes over huge
303
+ trees are reported as truncated. Narrow watch globs audit completely.
304
+ - `audit` sends in-scope file contents to the model, and a determined
305
+ prompt-injection in governed code can still influence a verdict —
306
+ deterministic rungs carry the real authority; `supervise`+`audit` is the
307
+ soft, advisory tier.
308
+
309
+ ## History
310
+
311
+ See [CHANGELOG.md](CHANGELOG.md). Charter was previously named governor;
312
+ v0.4.0 renamed it and added the local trust gate.
@@ -0,0 +1,287 @@
1
+ # charter — the design document becomes the charter
2
+
3
+ Your design doc says:
4
+
5
+ > Auth tokens are HMAC, never JWT.
6
+
7
+ ```bash
8
+ $ charter annotate SPEC.md # LLM turns prose into enforceable decisions
9
+ $ cat CHARTER.md
10
+ [D-001] Auth tokens are HMAC, never JWT -> assert: ! grep -rqE "jwt|jsonwebtoken" src
11
+ $ charter approve --why "initial review"
12
+ ```
13
+
14
+ Weeks later, an AI agent adds JWT code.
15
+
16
+ ```bash
17
+ $ charter check
18
+ FAIL D-001 "Auth tokens are HMAC, never JWT" — assert FAILED
19
+ ```
20
+
21
+ The agent fixes it. Nobody was interrupted, nothing was forgotten, and
22
+ `charter trace D-001` shows every file that implements the decision.
23
+
24
+ That's the whole idea: **executable design intent for AI-coded repos** —
25
+ ADRs + linter + traceability, in one file with almost no state.
26
+
27
+ The doctrine in one sentence: **a decision with no jurisdiction is not
28
+ governed.** Every decision names an enforcer; a supervise-only decision with
29
+ neither code citations nor an `@` watch scope fails check. CHARTER.md is the
30
+ constitution, `check` is the court, `audit` is the judge for gray areas, and
31
+ `[D-xxx]` citations are the map.
32
+
33
+ Try it in 30 seconds: `sh demo/run_demo.sh` (on Windows, run it from Git
34
+ Bash) — an agent adds Supabase to a local-first app and check catches it.
35
+ No API key needed.
36
+
37
+ ## Quick start
38
+
39
+ See it work first — the demo is offline and needs no API key (on Windows,
40
+ run it from Git Bash):
41
+
42
+ ```bash
43
+ git clone https://github.com/cspergel/Charter
44
+ cd Charter
45
+ sh demo/run_demo.sh # an agent adds Supabase to a local-first app; check catches it
46
+ ```
47
+
48
+ Then use it on your own repo. There are two ways to run it:
49
+
50
+ ```bash
51
+ # Option A — zero install. It's one file, zero dependencies (Python 3.10+).
52
+ python /path/to/charter.py check
53
+
54
+ # Option B — install the `charter` command.
55
+ pip install charter-intent # the command is `charter`; `charter` was taken on PyPI
56
+ # — or from a local checkout: pip install .
57
+ charter check
58
+ ```
59
+
60
+ `annotate` (turning a prose doc into decisions) needs an LLM backend; point it
61
+ at Claude Code with no API key required:
62
+
63
+ ```bash
64
+ export CHARTER_LLM_CMD="claude -p" # or set ANTHROPIC_API_KEY
65
+ charter annotate SPEC.md
66
+ charter approve --why "initial review"
67
+ charter check
68
+ charter doctor # checks your setup is sound
69
+ ```
70
+
71
+ State on disk: `CHARTER.md` (yours), `.charter/ledger.jsonl` (append-only
72
+ journal), and `.charter/charter.sha` (approval hash — commit it). Permission to
73
+ *execute* asserts is recorded in a per-user trust store **outside** the repo
74
+ (`~/.charter/trust`, keyed by repo path), so nothing a repo ships can grant
75
+ itself execution.
76
+
77
+ ## Security, in one paragraph
78
+
79
+ `charter check` executes shell commands defined in CHARTER.md (the assert
80
+ enforcers). A freshly cloned repo will **not** execute its asserts — even if it
81
+ ships an approval hash, and even if it ships a forged trust marker — until you
82
+ review CHARTER.md and run `charter approve` yourself, because the trust record
83
+ lives in a per-user store outside the repo. CI opts in explicitly with
84
+ `CHARTER_TRUST_ASSERTS=1`. `annotate`/`audit` send doc and file contents to
85
+ your configured LLM backend; nothing else makes network calls. Details and
86
+ threat model: [SECURITY.md](SECURITY.md).
87
+
88
+ ## The lifecycle
89
+
90
+ ```
91
+ charter annotate SPEC.md # LLM reads your prose doc, extracts binding
92
+ # decisions, assigns [D-xxx] symbols, proposes
93
+ # the lowest viable enforcer per decision,
94
+ # writes CHARTER.md + SPEC.annotated.md
95
+ # (charter init creates an empty CHARTER.md
96
+ # if you'd rather write it by hand)
97
+ <review CHARTER.md once> # the only mandatory human moment: adjust
98
+ # enforcers, strengthen supervise items
99
+ charter approve --why "..." # the human gate: journaled, hash-stamped
100
+ charter check # deterministic, free — pre-commit + CI
101
+ charter audit # judged pass over supervise-tier (PR-time)
102
+ charter digest [--mark] # batch-review everything the system did
103
+ charter trace D-001 # everything that traces to a decision
104
+ charter graph [--json] # the derived graph (Mermaid / machine-readable)
105
+ charter explain D-001 # the full story of one decision
106
+ charter doctor # setup-health checks
107
+ charter install-hook # pre-commit hook + Claude Code settings block
108
+ ```
109
+
110
+ ## The line syntax
111
+
112
+ ```
113
+ [D-001] title -> assert: <must-pass> !! <proof-must-succeed> @ glob, glob
114
+ [D-002] title -> supervise @ src/db/**
115
+ ```
116
+
117
+ - The enforcer kind is one of the ladder below.
118
+ - `!!` introduces an assert's **tripwire**: a probe that must succeed,
119
+ proving the detector can detect a known violation sample (a typo'd grep
120
+ path can't pass forever). The canonical pattern is
121
+ `echo <violation-sample> | <the-real-detector>`.
122
+ - `@` declares **watch scope**: a human-set jurisdiction floor. Audit reads
123
+ cited files ∪ watched files, so an uncited violating file is still seen.
124
+
125
+ ## The five layers
126
+
127
+ 1. **Annotate** — the bootstrap agent. Extraction is conservative
128
+ (contracts, not preferences — "keep the code simple" is correctly
129
+ ignored), capped at 15 by default (`--cap N`), dedupes against decisions
130
+ already indexed, and annotation of your original doc is non-destructive
131
+ (writes a `.annotated` copy with symbols inlined at the source sentences).
132
+ 2. **Enforce** — the ladder, strongest first: `structure > type > test >
133
+ lint > assert > supervise`. During review, push supervise items toward
134
+ the stronger deterministic rungs. `check` fails on: aspirational
135
+ decisions (no enforcer), missing enforcer targets, **enforcer rot** (the
136
+ `#Symbol` vanished in a refactor), failing asserts, and **blind
137
+ decisions** (supervise-only with no citations and no watch scope). A
138
+ proposed enforcer that doesn't exist yet is a **build obligation** —
139
+ check stays red until the builder creates the type/test, which is
140
+ governance generating the skeleton of the system. `check --budget N`
141
+ warns when judgment-only decisions outgrow the budget (default 5).
142
+ 3. **Trace** — builders leave `[D-xxx]` citations in comments and commits.
143
+ The graph is **derived from grep on every run, never stored** — so it can
144
+ never go stale.
145
+ 4. **Supervise** — `audit` judges only the supervise tier, and **citations
146
+ are the scope**: the auditor reads exactly the files that claim to
147
+ implement the decision, plus watched files. Verdicts: COMPLIES (ok line,
148
+ exit 0), VIOLATES (exit 1 — fix the code), AMBIGUOUS (flagged for digest
149
+ review). All verdicts land in the ledger. No backend configured →
150
+ everything AMBIGUOUS, never crashes.
151
+ 5. **Steer** — one optional SessionStart hook injects the whole index
152
+ (~15 one-liners, a few hundred tokens, once per session) plus the
153
+ citation protocol. No gates: agents stay in their native loop — cite the
154
+ symbol, keep `check` green.
155
+
156
+ ## LLM backends
157
+
158
+ Resolution order for `annotate` and `audit`:
159
+
160
+ 1. `CHARTER_LLM_CMD` — any command that reads the prompt on stdin and
161
+ prints the reply on stdout. Point it at Claude Code headless:
162
+ `export CHARTER_LLM_CMD="claude -p"` — rides your existing plan.
163
+ 2. `ANTHROPIC_API_KEY` — direct API (Sonnet for annotation quality, Haiku
164
+ for cheap audit verdicts; override with `CHARTER_ANNOTATE_MODEL` /
165
+ `CHARTER_AUDIT_MODEL`).
166
+ 3. Neither — `annotate` explains itself; `audit` degrades to AMBIGUOUS.
167
+
168
+ ## Integration
169
+
170
+ `.git/hooks/pre-commit` (or just run `charter install-hook`):
171
+ ```bash
172
+ python charter.py check || exit 1
173
+ ```
174
+
175
+ CI on PRs (the judged layer) — note the explicit opt-in, and treat PRs that
176
+ modify CHARTER.md like PRs that modify your CI workflows:
177
+ ```bash
178
+ CHARTER_TRUST_ASSERTS=1 python charter.py check && python charter.py audit
179
+ ```
180
+
181
+ `.claude/settings.json` (optional steering):
182
+ ```json
183
+ {
184
+ "hooks": {
185
+ "SessionStart": [
186
+ { "hooks": [ { "type": "command", "command": "python charter.py hook" } ] }
187
+ ]
188
+ }
189
+ }
190
+ ```
191
+
192
+ For non-hook agents (Cursor, aider), put this in `AGENTS.md`/`.cursorrules`:
193
+
194
+ > This repo's binding decisions live in CHARTER.md. When your work implements
195
+ > or touches a decision, leave its `[D-xxx]` symbol in a nearby comment and
196
+ > your commit message. Run `python charter.py check` before finishing; a
197
+ > failure means an enforcer caught a violation — fix the code, never the
198
+ > enforcer. Conflicts between a request and a decision must be surfaced, not
199
+ > silently resolved.
200
+
201
+ ## Liberties taken, and why
202
+
203
+ - **Citations replace scope globs.** The derived graph defines what each
204
+ decision governs. This deleted the lockfile, ack protocol, session
205
+ baselines, and per-edit hooks of earlier designs — the single largest
206
+ overhead reduction — at the cost of relying on builders to cite. The
207
+ steering hook + agent instructions make citing the path of least
208
+ resistance, and `check` fails supervise decisions that end up blind.
209
+ - **Stateless judgment.** `audit` judges *current* state, not drift-since —
210
+ so there is nothing to pin, ack, or reconcile. Run it whenever; the ledger
211
+ is the only memory, and it's append-only and reviewable.
212
+ - **The graph navigates; enforcers govern.** `graph --json` exists for
213
+ agents to ask "what connects to what," but no verdict ever comes from
214
+ graph topology — authority lives in things that can't be argued with.
215
+
216
+ ## FAQ
217
+
218
+ **Isn't this just a pre-commit hook that runs grep?**
219
+ At the deterministic layer, yes — and that's the point. A grep that can't be
220
+ argued with beats an LLM that can be talked out of a verdict. Charter's value
221
+ isn't a cleverer check; it's turning prose decisions into checks at all,
222
+ keeping them in sync with the code via citations, and proving the checks aren't
223
+ vacuous (tripwires). The grep is a feature, not an embarrassment.
224
+
225
+ **Why not Spec Kit / OpenSpec / Kiro?**
226
+ Those govern code *generation* — write a spec, then generate from it. They're
227
+ out of the loop the moment a later change quietly contradicts the original
228
+ design, which is where drift actually accrues. Charter governs the repo from
229
+ then on, on every commit. They compose: scaffold with whatever you like, keep
230
+ it true with Charter.
231
+
232
+ **An LLM wrote my enforcement rules — why would I trust that?**
233
+ You don't trust it — you review it. `annotate` only *proposes*; nothing takes
234
+ effect until you read CHARTER.md and `approve` it, exactly like reading code
235
+ you're about to run. At enforcement time there's no LLM in the loop: `check` is
236
+ deterministic shell. The model proposes, you ratify, grep decides.
237
+
238
+ **What stops an agent from editing CHARTER.md, or weakening an enforcer, to make
239
+ check pass?**
240
+ Any change to CHARTER.md fails `check` until a human runs `approve` (a hashed,
241
+ journaled gate) — so an agent can't quietly rewrite the constitution. The agent
242
+ instructions say *fix the code, never the enforcer*, and a weakened assert trips
243
+ its tripwire (the proof that it can still catch a known violation). Tampering is
244
+ visible, not silent.
245
+
246
+ **Won't grep-based asserts be brittle and false-positive?**
247
+ Some will — which is why the ladder exists. Push fragile checks up to `type`,
248
+ `test`, or `lint`, where the language and your test runner do the work; reserve
249
+ `assert` for things that genuinely are a grep. Tripwires flag asserts that have
250
+ quietly stopped detecting anything, so a brittle check fails loudly rather than
251
+ passing forever.
252
+
253
+ **Does it lock me into Claude?**
254
+ No. Any backend that reads a prompt on stdin works (`CHARTER_LLM_CMD`), the
255
+ Anthropic API works, and you can skip the LLM entirely and write CHARTER.md by
256
+ hand — `check` never calls a model.
257
+
258
+ ## Known limits
259
+
260
+ - **`check` executes shell from CHARTER.md.** The trust gate means a cloned
261
+ repo can't run code on your machine before you review it, but after you
262
+ approve, the asserts are exactly as trustworthy as your review of them.
263
+ Read them like code you are about to run — because they are.
264
+ - A builder that never cites makes citation-only supervise decisions blind —
265
+ check fails them rather than letting them silently un-govern. Decisions
266
+ with `@` watch globs are still audited via watched files. Deterministic
267
+ rungs are immune — prefer them.
268
+ - Annotation quality is bounded by the doc: vague prose yields supervise
269
+ proposals. The review-once step is where you strengthen enforcers.
270
+ - `assert` commands are POSIX-shell; on Windows they run under Git Bash
271
+ (auto-detected, `CHARTER_SHELL` overrides).
272
+ - A vacuous assert's `!! proof` is authored by the same source as the
273
+ assert, so the tripwire raises the bar but can't fully self-police —
274
+ `check` flags trivially-true probes (`!! true`, bare `echo`), but a
275
+ cleverly matched fake proof still needs the human review-once gate.
276
+ - `audit` judges at most the first 60 in-scope files per decision (chunked,
277
+ worst-verdict-wins) to bound LLM cost; broad `@ src/**` scopes over huge
278
+ trees are reported as truncated. Narrow watch globs audit completely.
279
+ - `audit` sends in-scope file contents to the model, and a determined
280
+ prompt-injection in governed code can still influence a verdict —
281
+ deterministic rungs carry the real authority; `supervise`+`audit` is the
282
+ soft, advisory tier.
283
+
284
+ ## History
285
+
286
+ See [CHANGELOG.md](CHANGELOG.md). Charter was previously named governor;
287
+ v0.4.0 renamed it and added the local trust gate.