exitzero 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.
- exitzero-0.1.0/LICENSE +21 -0
- exitzero-0.1.0/PKG-INFO +234 -0
- exitzero-0.1.0/README.md +224 -0
- exitzero-0.1.0/exitzero.egg-info/PKG-INFO +234 -0
- exitzero-0.1.0/exitzero.egg-info/SOURCES.txt +28 -0
- exitzero-0.1.0/exitzero.egg-info/dependency_links.txt +1 -0
- exitzero-0.1.0/exitzero.egg-info/entry_points.txt +6 -0
- exitzero-0.1.0/exitzero.egg-info/top_level.txt +5 -0
- exitzero-0.1.0/packages/core/src/exitzero/__init__.py +3 -0
- exitzero-0.1.0/packages/core/src/exitzero/__main__.py +3 -0
- exitzero-0.1.0/packages/core/src/exitzero/api.py +69 -0
- exitzero-0.1.0/packages/core/src/exitzero/cli.py +208 -0
- exitzero-0.1.0/packages/core/src/exitzero/files.py +51 -0
- exitzero-0.1.0/packages/core/src/exitzero/hooks.py +130 -0
- exitzero-0.1.0/packages/core/src/exitzero/ledger.py +25 -0
- exitzero-0.1.0/packages/core/src/exitzero/loader.py +19 -0
- exitzero-0.1.0/packages/core/src/exitzero/policy.py +171 -0
- exitzero-0.1.0/packages/core/src/exitzero/runner.py +102 -0
- exitzero-0.1.0/packages/plugin-harness/src/exitzero_harness/__init__.py +248 -0
- exitzero-0.1.0/packages/plugin-ledger/src/exitzero_ledger/__init__.py +12 -0
- exitzero-0.1.0/packages/plugin-mcp-gateway/src/exitzero_mcp_gateway/__init__.py +12 -0
- exitzero-0.1.0/packages/plugin-verify/src/exitzero_verify/__init__.py +459 -0
- exitzero-0.1.0/pyproject.toml +23 -0
- exitzero-0.1.0/setup.cfg +4 -0
- exitzero-0.1.0/tests/test_core.py +192 -0
- exitzero-0.1.0/tests/test_harness.py +231 -0
- exitzero-0.1.0/tests/test_hooks.py +145 -0
- exitzero-0.1.0/tests/test_init.py +141 -0
- exitzero-0.1.0/tests/test_release_runner.py +37 -0
- exitzero-0.1.0/tests/test_verify.py +184 -0
exitzero-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 exitzero 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.
|
exitzero-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: exitzero
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Offline policy and verification gates for AI-assisted coding teams
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# exitzero
|
|
12
|
+
|
|
13
|
+
**AI가 “끝났다”고 말해도, 검사를 통과하기 전에는 끝난 것이 아닙니다.**
|
|
14
|
+
|
|
15
|
+
exitzero는 저장소의 정책을 실행하는 작은 개발 도구입니다. 같은 TOML 정책으로
|
|
16
|
+
로컬 CLI, Git 훅, CI를 검사하고 매번 JSON 실행 영수증을 남깁니다. 사용자는 하나의
|
|
17
|
+
명령을 쓰고, 내부는 작은 코어와 플러그인으로 나뉩니다.
|
|
18
|
+
|
|
19
|
+
**An agent saying “done” is not evidence.** Run the policy, check the exit code,
|
|
20
|
+
and keep the receipt. This MVP checks Python code and agent configuration.
|
|
21
|
+
Explicit command checks can run your existing tools for any language.
|
|
22
|
+
|
|
23
|
+
## Try it without downloading dependencies
|
|
24
|
+
|
|
25
|
+
Python 3.11 or newer is required. Runtime and tests use only the standard library.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
export PATH="$PWD/bin:$PATH"
|
|
29
|
+
mkdir /tmp/exitzero-demo
|
|
30
|
+
cd /tmp/exitzero-demo
|
|
31
|
+
exitzero init
|
|
32
|
+
exitzero check
|
|
33
|
+
exitzero lint-config
|
|
34
|
+
exitzero report --format json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`init` creates a starter TOML policy, a managed section in `AGENTS.md`, and ignore
|
|
38
|
+
entries for local receipts and Python caches. In an empty repository it also
|
|
39
|
+
creates a tiny Python sample. It preserves existing policy files. The starter
|
|
40
|
+
policy checks syntax only: add project-specific checks before using it as a merge
|
|
41
|
+
gate. A syntax pass is not a claim that your application works.
|
|
42
|
+
|
|
43
|
+
For a Python repository, `init` can write the common static checks and your
|
|
44
|
+
existing test/review commands in one step. Each command is parsed into argv and
|
|
45
|
+
later runs with `shell=False`; `{python}` means the Python interpreter running
|
|
46
|
+
`exitzero`.
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
exitzero init --profile python \
|
|
50
|
+
--source-root src --source-root tests \
|
|
51
|
+
--allow-module numpy --allow-module pytest \
|
|
52
|
+
--test-command '{python} -m pytest' \
|
|
53
|
+
--review-command '{python} scripts/review_contract.py'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`--source-root`, `--allow-module`, and `--review-command` can be repeated. Quote
|
|
57
|
+
literal arguments that contain punctuation; shell pipelines, redirects, and
|
|
58
|
+
other control operators are rejected. `init` only records commands, so it does
|
|
59
|
+
not execute them. Keep credentials out of command arguments because the policy
|
|
60
|
+
stores the resulting argv. Existing policies are never overwritten, and
|
|
61
|
+
generation options cannot be combined with `init --sync`. Without
|
|
62
|
+
`--profile python`, `init` remains the syntax-only compatibility starter.
|
|
63
|
+
Generated command checks fingerprint Python files for the receipt. If a test or
|
|
64
|
+
review command depends on JSON, YAML, Markdown, or another non-Python input,
|
|
65
|
+
edit that check's `paths` in the policy to include those files.
|
|
66
|
+
|
|
67
|
+
Run the included example, which exercises all four check types:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
./bin/exitzero --root examples/sample check
|
|
71
|
+
./bin/exitzero --root examples/sample lint-config
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For a conventional installation, use a virtual environment and `python -m pip
|
|
75
|
+
install .`. Building uses setuptools; runtime has no third-party dependencies.
|
|
76
|
+
If setuptools and wheel are already available, an offline editable install is
|
|
77
|
+
`python -m pip install --no-index --no-build-isolation --no-deps -e .`.
|
|
78
|
+
The checkout launcher above needs no build tools.
|
|
79
|
+
|
|
80
|
+
## Put review requirements in the policy
|
|
81
|
+
|
|
82
|
+
```toml
|
|
83
|
+
version = 1
|
|
84
|
+
plugins = ["exitzero_verify", "exitzero_harness"]
|
|
85
|
+
|
|
86
|
+
[[checks]]
|
|
87
|
+
id = "syntax"
|
|
88
|
+
kind = "python.syntax"
|
|
89
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
90
|
+
|
|
91
|
+
[[checks]]
|
|
92
|
+
id = "imports"
|
|
93
|
+
kind = "python.imports"
|
|
94
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
95
|
+
[checks.options]
|
|
96
|
+
roots = ["src", "."]
|
|
97
|
+
allow_modules = []
|
|
98
|
+
|
|
99
|
+
[[checks]]
|
|
100
|
+
id = "test-quality"
|
|
101
|
+
kind = "python.test-quality"
|
|
102
|
+
paths = ["tests/test_*.py"]
|
|
103
|
+
|
|
104
|
+
[[checks]]
|
|
105
|
+
id = "review-contracts"
|
|
106
|
+
kind = "command"
|
|
107
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
108
|
+
[checks.options]
|
|
109
|
+
argv = ["{python}", "-m", "unittest", "discover", "-s", "tests", "-v"]
|
|
110
|
+
timeout = 30
|
|
111
|
+
|
|
112
|
+
[harness]
|
|
113
|
+
config_files = []
|
|
114
|
+
rules = [{id = "error-text", value = "Tests assert the exact public error text."}]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
After editing the policy, run `exitzero init --sync`. Only the generated section
|
|
118
|
+
of `AGENTS.md` changes. Its fingerprint covers the complete parsed policy, so
|
|
119
|
+
changing check options also creates detectable drift. Text outside the section
|
|
120
|
+
stays yours. Harness rules are documentation and conflict detection, not semantic
|
|
121
|
+
enforcement: express exact messages, types and result ordering in executable
|
|
122
|
+
tests. See [the sample](examples/sample).
|
|
123
|
+
|
|
124
|
+
| Check | What v1 detects |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `python.syntax` | Python that cannot be parsed |
|
|
127
|
+
| `python.imports` | Unresolved modules and missing statically declared local module symbols |
|
|
128
|
+
| `python.test-quality` | No test cases, empty tests, obvious constant-only assertions |
|
|
129
|
+
| `command` | A configured test/lint command fails or exceeds its timeout |
|
|
130
|
+
| Harness lint | Generated AGENTS drift, installed-hook drift, explicit JSON config shape errors, repeated/conflicting rule IDs |
|
|
131
|
+
|
|
132
|
+
Import analysis does not execute imported code. It is intentionally conservative
|
|
133
|
+
and does not prove arbitrary dynamic exports, package loading or third-party API
|
|
134
|
+
signatures. `allow_modules` explicitly trusts listed external module names.
|
|
135
|
+
Test-quality analysis detects obvious problems; run real tests as well. Natural
|
|
136
|
+
language contradictions in arbitrary AGENTS prose or Cursor rule files are not
|
|
137
|
+
understood by v1.
|
|
138
|
+
|
|
139
|
+
## Commands and outcomes
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
exitzero init
|
|
143
|
+
exitzero init --sync
|
|
144
|
+
exitzero check --format json
|
|
145
|
+
exitzero lint-config --format json
|
|
146
|
+
exitzero hooks install --adapter cursor
|
|
147
|
+
exitzero hooks install --adapter pre-commit
|
|
148
|
+
exitzero hooks run --slot CI --format json
|
|
149
|
+
exitzero report --format json
|
|
150
|
+
exitzero plugin harness-eval # Explicitly unavailable in v1: exit 2.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Global `--root` and `--policy` options go before the subcommand. `check` runs
|
|
154
|
+
configuration linters and verification checks. `lint-config` never executes
|
|
155
|
+
verification commands.
|
|
156
|
+
|
|
157
|
+
| Exit code | Meaning |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| 0 | All configured checks passed |
|
|
160
|
+
| 1 | A check found a violation |
|
|
161
|
+
| 2 | Invalid policy, missing plugin, execution error, or receipt could not be written |
|
|
162
|
+
|
|
163
|
+
Every `check`, `lint-config`, and hook gate writes a unique JSON receipt under
|
|
164
|
+
`.exitzero/runs/`, including failures and malformed policies. If storage fails,
|
|
165
|
+
the command exits 2 and reports `receipt: null`; it cannot claim success.
|
|
166
|
+
`--format json` prints the same machine-readable result. `report` reads the
|
|
167
|
+
latest receipt; it does not run a fresh check. See [receipt schema](docs/receipt.schema.json).
|
|
168
|
+
|
|
169
|
+
Receipts include check IDs, findings, exit code, policy hash, hashes of selected
|
|
170
|
+
inputs, plugin names and timing. They do not contain source code, environment
|
|
171
|
+
variables, hook input, command arguments or command output. Command output is
|
|
172
|
+
discarded; rerun a failing command directly to debug it. Receipts identify the
|
|
173
|
+
declared input selection, not every dependency of arbitrary commands. They are
|
|
174
|
+
local evidence, not signed or tamper-proof attestations.
|
|
175
|
+
|
|
176
|
+
## Local hooks and CI
|
|
177
|
+
|
|
178
|
+
See [hook setup](docs/HOOKS.md). Cursor uses a `stop` hook by default: failures
|
|
179
|
+
request one follow-up repair turn. This is feedback, not a merge barrier. Git
|
|
180
|
+
pre-commit and CI enforce exit codes. The generic hook command has the same
|
|
181
|
+
0/1/2 contract as `check`; Cursor translates results to its JSON protocol.
|
|
182
|
+
|
|
183
|
+
Run the repository's automated milestone runner:
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
python3 scripts/ci.py
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
It runs the repository gate, config lint, sample gate and ten pass/fail fixtures,
|
|
190
|
+
and writes `.exitzero/ci-results.json` plus logs. The GitHub workflow runs this
|
|
191
|
+
same script and uploads `.exitzero/` evidence even on failure. Configure the CI
|
|
192
|
+
job as a required branch check in your hosting service; this repository does not
|
|
193
|
+
change branch protection settings.
|
|
194
|
+
|
|
195
|
+
The [riskgate pilot](docs/PILOT_RISKGATE.md) applies the same gate to a pinned
|
|
196
|
+
real repository. It checks a passing baseline and four independent faults,
|
|
197
|
+
including an empty test that the upstream test runner still accepts. Its runner
|
|
198
|
+
preserves the original checkout and records all gate receipts.
|
|
199
|
+
The [vecdiff pilot](docs/PILOT_VECDIFF.md) adds external NumPy dependencies and
|
|
200
|
+
independent numeric review contracts. Both pilots use isolated source copies.
|
|
201
|
+
|
|
202
|
+
## Trust and scope
|
|
203
|
+
|
|
204
|
+
Policies, selected plugins and command checks are trusted executable configuration.
|
|
205
|
+
Review them before running an unfamiliar repository. Static checks and config
|
|
206
|
+
lint make no network requests. Command checks can run arbitrary local programs;
|
|
207
|
+
choose offline commands to keep the whole gate offline. This is not an execution
|
|
208
|
+
sandbox or the future MCP allowlist gateway. Config files are read only when
|
|
209
|
+
explicitly selected (and the installed Cursor file is fingerprinted); do not
|
|
210
|
+
include credential files. Known credential-like paths and symlink targets are
|
|
211
|
+
rejected. Path filtering is not a universal secret detector.
|
|
212
|
+
|
|
213
|
+
There is no cloud service, model hosting, model training, full agent evaluation,
|
|
214
|
+
proxy gateway, PR publisher or automatic rollback in v1.
|
|
215
|
+
|
|
216
|
+
## Structure and contributing
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
packages/core policy, CLI, hook slots, plugin loader, receipts
|
|
220
|
+
packages/plugin-verify verification rules and command checks
|
|
221
|
+
packages/plugin-harness configuration lint; eval command stub
|
|
222
|
+
packages/plugin-mcp-gateway v1.2 interface stub
|
|
223
|
+
packages/plugin-ledger v1.3 interface stub
|
|
224
|
+
fixtures/ ten positive and negative repository cases
|
|
225
|
+
examples/sample/ runnable error-text/type/order contract example
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Read [Plugin API](docs/PLUGIN_API.md), [roadmap](ROADMAP.md), and
|
|
229
|
+
[design references](docs/REFERENCES.md). No project code was copied from prior art.
|
|
230
|
+
Run focused regression tests with `python3 scripts/run_tests.py`; run the complete
|
|
231
|
+
local acceptance sequence with `python3 scripts/ci.py`.
|
|
232
|
+
Verify a built package and real Git-hook behavior with the [offline release
|
|
233
|
+
runner](docs/RELEASE.md). See [release notes](CHANGELOG.md) for the candidate scope.
|
|
234
|
+
License: [MIT](LICENSE).
|
exitzero-0.1.0/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# exitzero
|
|
2
|
+
|
|
3
|
+
**AI가 “끝났다”고 말해도, 검사를 통과하기 전에는 끝난 것이 아닙니다.**
|
|
4
|
+
|
|
5
|
+
exitzero는 저장소의 정책을 실행하는 작은 개발 도구입니다. 같은 TOML 정책으로
|
|
6
|
+
로컬 CLI, Git 훅, CI를 검사하고 매번 JSON 실행 영수증을 남깁니다. 사용자는 하나의
|
|
7
|
+
명령을 쓰고, 내부는 작은 코어와 플러그인으로 나뉩니다.
|
|
8
|
+
|
|
9
|
+
**An agent saying “done” is not evidence.** Run the policy, check the exit code,
|
|
10
|
+
and keep the receipt. This MVP checks Python code and agent configuration.
|
|
11
|
+
Explicit command checks can run your existing tools for any language.
|
|
12
|
+
|
|
13
|
+
## Try it without downloading dependencies
|
|
14
|
+
|
|
15
|
+
Python 3.11 or newer is required. Runtime and tests use only the standard library.
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
export PATH="$PWD/bin:$PATH"
|
|
19
|
+
mkdir /tmp/exitzero-demo
|
|
20
|
+
cd /tmp/exitzero-demo
|
|
21
|
+
exitzero init
|
|
22
|
+
exitzero check
|
|
23
|
+
exitzero lint-config
|
|
24
|
+
exitzero report --format json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`init` creates a starter TOML policy, a managed section in `AGENTS.md`, and ignore
|
|
28
|
+
entries for local receipts and Python caches. In an empty repository it also
|
|
29
|
+
creates a tiny Python sample. It preserves existing policy files. The starter
|
|
30
|
+
policy checks syntax only: add project-specific checks before using it as a merge
|
|
31
|
+
gate. A syntax pass is not a claim that your application works.
|
|
32
|
+
|
|
33
|
+
For a Python repository, `init` can write the common static checks and your
|
|
34
|
+
existing test/review commands in one step. Each command is parsed into argv and
|
|
35
|
+
later runs with `shell=False`; `{python}` means the Python interpreter running
|
|
36
|
+
`exitzero`.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
exitzero init --profile python \
|
|
40
|
+
--source-root src --source-root tests \
|
|
41
|
+
--allow-module numpy --allow-module pytest \
|
|
42
|
+
--test-command '{python} -m pytest' \
|
|
43
|
+
--review-command '{python} scripts/review_contract.py'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`--source-root`, `--allow-module`, and `--review-command` can be repeated. Quote
|
|
47
|
+
literal arguments that contain punctuation; shell pipelines, redirects, and
|
|
48
|
+
other control operators are rejected. `init` only records commands, so it does
|
|
49
|
+
not execute them. Keep credentials out of command arguments because the policy
|
|
50
|
+
stores the resulting argv. Existing policies are never overwritten, and
|
|
51
|
+
generation options cannot be combined with `init --sync`. Without
|
|
52
|
+
`--profile python`, `init` remains the syntax-only compatibility starter.
|
|
53
|
+
Generated command checks fingerprint Python files for the receipt. If a test or
|
|
54
|
+
review command depends on JSON, YAML, Markdown, or another non-Python input,
|
|
55
|
+
edit that check's `paths` in the policy to include those files.
|
|
56
|
+
|
|
57
|
+
Run the included example, which exercises all four check types:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
./bin/exitzero --root examples/sample check
|
|
61
|
+
./bin/exitzero --root examples/sample lint-config
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For a conventional installation, use a virtual environment and `python -m pip
|
|
65
|
+
install .`. Building uses setuptools; runtime has no third-party dependencies.
|
|
66
|
+
If setuptools and wheel are already available, an offline editable install is
|
|
67
|
+
`python -m pip install --no-index --no-build-isolation --no-deps -e .`.
|
|
68
|
+
The checkout launcher above needs no build tools.
|
|
69
|
+
|
|
70
|
+
## Put review requirements in the policy
|
|
71
|
+
|
|
72
|
+
```toml
|
|
73
|
+
version = 1
|
|
74
|
+
plugins = ["exitzero_verify", "exitzero_harness"]
|
|
75
|
+
|
|
76
|
+
[[checks]]
|
|
77
|
+
id = "syntax"
|
|
78
|
+
kind = "python.syntax"
|
|
79
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
80
|
+
|
|
81
|
+
[[checks]]
|
|
82
|
+
id = "imports"
|
|
83
|
+
kind = "python.imports"
|
|
84
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
85
|
+
[checks.options]
|
|
86
|
+
roots = ["src", "."]
|
|
87
|
+
allow_modules = []
|
|
88
|
+
|
|
89
|
+
[[checks]]
|
|
90
|
+
id = "test-quality"
|
|
91
|
+
kind = "python.test-quality"
|
|
92
|
+
paths = ["tests/test_*.py"]
|
|
93
|
+
|
|
94
|
+
[[checks]]
|
|
95
|
+
id = "review-contracts"
|
|
96
|
+
kind = "command"
|
|
97
|
+
paths = ["src/**/*.py", "tests/**/*.py"]
|
|
98
|
+
[checks.options]
|
|
99
|
+
argv = ["{python}", "-m", "unittest", "discover", "-s", "tests", "-v"]
|
|
100
|
+
timeout = 30
|
|
101
|
+
|
|
102
|
+
[harness]
|
|
103
|
+
config_files = []
|
|
104
|
+
rules = [{id = "error-text", value = "Tests assert the exact public error text."}]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
After editing the policy, run `exitzero init --sync`. Only the generated section
|
|
108
|
+
of `AGENTS.md` changes. Its fingerprint covers the complete parsed policy, so
|
|
109
|
+
changing check options also creates detectable drift. Text outside the section
|
|
110
|
+
stays yours. Harness rules are documentation and conflict detection, not semantic
|
|
111
|
+
enforcement: express exact messages, types and result ordering in executable
|
|
112
|
+
tests. See [the sample](examples/sample).
|
|
113
|
+
|
|
114
|
+
| Check | What v1 detects |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| `python.syntax` | Python that cannot be parsed |
|
|
117
|
+
| `python.imports` | Unresolved modules and missing statically declared local module symbols |
|
|
118
|
+
| `python.test-quality` | No test cases, empty tests, obvious constant-only assertions |
|
|
119
|
+
| `command` | A configured test/lint command fails or exceeds its timeout |
|
|
120
|
+
| Harness lint | Generated AGENTS drift, installed-hook drift, explicit JSON config shape errors, repeated/conflicting rule IDs |
|
|
121
|
+
|
|
122
|
+
Import analysis does not execute imported code. It is intentionally conservative
|
|
123
|
+
and does not prove arbitrary dynamic exports, package loading or third-party API
|
|
124
|
+
signatures. `allow_modules` explicitly trusts listed external module names.
|
|
125
|
+
Test-quality analysis detects obvious problems; run real tests as well. Natural
|
|
126
|
+
language contradictions in arbitrary AGENTS prose or Cursor rule files are not
|
|
127
|
+
understood by v1.
|
|
128
|
+
|
|
129
|
+
## Commands and outcomes
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
exitzero init
|
|
133
|
+
exitzero init --sync
|
|
134
|
+
exitzero check --format json
|
|
135
|
+
exitzero lint-config --format json
|
|
136
|
+
exitzero hooks install --adapter cursor
|
|
137
|
+
exitzero hooks install --adapter pre-commit
|
|
138
|
+
exitzero hooks run --slot CI --format json
|
|
139
|
+
exitzero report --format json
|
|
140
|
+
exitzero plugin harness-eval # Explicitly unavailable in v1: exit 2.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Global `--root` and `--policy` options go before the subcommand. `check` runs
|
|
144
|
+
configuration linters and verification checks. `lint-config` never executes
|
|
145
|
+
verification commands.
|
|
146
|
+
|
|
147
|
+
| Exit code | Meaning |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| 0 | All configured checks passed |
|
|
150
|
+
| 1 | A check found a violation |
|
|
151
|
+
| 2 | Invalid policy, missing plugin, execution error, or receipt could not be written |
|
|
152
|
+
|
|
153
|
+
Every `check`, `lint-config`, and hook gate writes a unique JSON receipt under
|
|
154
|
+
`.exitzero/runs/`, including failures and malformed policies. If storage fails,
|
|
155
|
+
the command exits 2 and reports `receipt: null`; it cannot claim success.
|
|
156
|
+
`--format json` prints the same machine-readable result. `report` reads the
|
|
157
|
+
latest receipt; it does not run a fresh check. See [receipt schema](docs/receipt.schema.json).
|
|
158
|
+
|
|
159
|
+
Receipts include check IDs, findings, exit code, policy hash, hashes of selected
|
|
160
|
+
inputs, plugin names and timing. They do not contain source code, environment
|
|
161
|
+
variables, hook input, command arguments or command output. Command output is
|
|
162
|
+
discarded; rerun a failing command directly to debug it. Receipts identify the
|
|
163
|
+
declared input selection, not every dependency of arbitrary commands. They are
|
|
164
|
+
local evidence, not signed or tamper-proof attestations.
|
|
165
|
+
|
|
166
|
+
## Local hooks and CI
|
|
167
|
+
|
|
168
|
+
See [hook setup](docs/HOOKS.md). Cursor uses a `stop` hook by default: failures
|
|
169
|
+
request one follow-up repair turn. This is feedback, not a merge barrier. Git
|
|
170
|
+
pre-commit and CI enforce exit codes. The generic hook command has the same
|
|
171
|
+
0/1/2 contract as `check`; Cursor translates results to its JSON protocol.
|
|
172
|
+
|
|
173
|
+
Run the repository's automated milestone runner:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
python3 scripts/ci.py
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
It runs the repository gate, config lint, sample gate and ten pass/fail fixtures,
|
|
180
|
+
and writes `.exitzero/ci-results.json` plus logs. The GitHub workflow runs this
|
|
181
|
+
same script and uploads `.exitzero/` evidence even on failure. Configure the CI
|
|
182
|
+
job as a required branch check in your hosting service; this repository does not
|
|
183
|
+
change branch protection settings.
|
|
184
|
+
|
|
185
|
+
The [riskgate pilot](docs/PILOT_RISKGATE.md) applies the same gate to a pinned
|
|
186
|
+
real repository. It checks a passing baseline and four independent faults,
|
|
187
|
+
including an empty test that the upstream test runner still accepts. Its runner
|
|
188
|
+
preserves the original checkout and records all gate receipts.
|
|
189
|
+
The [vecdiff pilot](docs/PILOT_VECDIFF.md) adds external NumPy dependencies and
|
|
190
|
+
independent numeric review contracts. Both pilots use isolated source copies.
|
|
191
|
+
|
|
192
|
+
## Trust and scope
|
|
193
|
+
|
|
194
|
+
Policies, selected plugins and command checks are trusted executable configuration.
|
|
195
|
+
Review them before running an unfamiliar repository. Static checks and config
|
|
196
|
+
lint make no network requests. Command checks can run arbitrary local programs;
|
|
197
|
+
choose offline commands to keep the whole gate offline. This is not an execution
|
|
198
|
+
sandbox or the future MCP allowlist gateway. Config files are read only when
|
|
199
|
+
explicitly selected (and the installed Cursor file is fingerprinted); do not
|
|
200
|
+
include credential files. Known credential-like paths and symlink targets are
|
|
201
|
+
rejected. Path filtering is not a universal secret detector.
|
|
202
|
+
|
|
203
|
+
There is no cloud service, model hosting, model training, full agent evaluation,
|
|
204
|
+
proxy gateway, PR publisher or automatic rollback in v1.
|
|
205
|
+
|
|
206
|
+
## Structure and contributing
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
packages/core policy, CLI, hook slots, plugin loader, receipts
|
|
210
|
+
packages/plugin-verify verification rules and command checks
|
|
211
|
+
packages/plugin-harness configuration lint; eval command stub
|
|
212
|
+
packages/plugin-mcp-gateway v1.2 interface stub
|
|
213
|
+
packages/plugin-ledger v1.3 interface stub
|
|
214
|
+
fixtures/ ten positive and negative repository cases
|
|
215
|
+
examples/sample/ runnable error-text/type/order contract example
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Read [Plugin API](docs/PLUGIN_API.md), [roadmap](ROADMAP.md), and
|
|
219
|
+
[design references](docs/REFERENCES.md). No project code was copied from prior art.
|
|
220
|
+
Run focused regression tests with `python3 scripts/run_tests.py`; run the complete
|
|
221
|
+
local acceptance sequence with `python3 scripts/ci.py`.
|
|
222
|
+
Verify a built package and real Git-hook behavior with the [offline release
|
|
223
|
+
runner](docs/RELEASE.md). See [release notes](CHANGELOG.md) for the candidate scope.
|
|
224
|
+
License: [MIT](LICENSE).
|