aeview 0.0.1__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.
- aeview-0.0.1/LICENSE +21 -0
- aeview-0.0.1/PKG-INFO +397 -0
- aeview-0.0.1/README.md +367 -0
- aeview-0.0.1/pyproject.toml +72 -0
- aeview-0.0.1/src/aeview/__init__.py +6 -0
- aeview-0.0.1/src/aeview/_data/DEDUPLICATION.md +26 -0
- aeview-0.0.1/src/aeview/_data/REVIEWER.md +51 -0
- aeview-0.0.1/src/aeview/_data/settings.json +8 -0
- aeview-0.0.1/src/aeview/activate.py +58 -0
- aeview-0.0.1/src/aeview/bundle.py +61 -0
- aeview-0.0.1/src/aeview/cli.py +897 -0
- aeview-0.0.1/src/aeview/config.py +126 -0
- aeview-0.0.1/src/aeview/dedup.py +119 -0
- aeview-0.0.1/src/aeview/doctor.py +86 -0
- aeview-0.0.1/src/aeview/fanout.py +133 -0
- aeview-0.0.1/src/aeview/harness/__init__.py +3 -0
- aeview-0.0.1/src/aeview/harness/base.py +165 -0
- aeview-0.0.1/src/aeview/harness/claude_code.py +271 -0
- aeview-0.0.1/src/aeview/harness/codex.py +350 -0
- aeview-0.0.1/src/aeview/harness/copilot.py +552 -0
- aeview-0.0.1/src/aeview/harness/eventlog.py +101 -0
- aeview-0.0.1/src/aeview/ignore.py +174 -0
- aeview-0.0.1/src/aeview/merge.py +251 -0
- aeview-0.0.1/src/aeview/process.py +120 -0
- aeview-0.0.1/src/aeview/prompt.py +63 -0
- aeview-0.0.1/src/aeview/report.py +87 -0
- aeview-0.0.1/src/aeview/resolve.py +262 -0
- aeview-0.0.1/src/aeview/runstore.py +337 -0
- aeview-0.0.1/src/aeview/schema.py +280 -0
- aeview-0.0.1/src/aeview/scope.py +462 -0
aeview-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MarlzRana
|
|
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.
|
aeview-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aeview
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Fan code reviewers across multiple agent harnesses and merge one verdict.
|
|
5
|
+
Keywords: code-review,ai,agents,cli
|
|
6
|
+
Author: MarlzRana
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Requires-Dist: typer>=0.12
|
|
18
|
+
Requires-Dist: pydantic>=2.7
|
|
19
|
+
Requires-Dist: pyyaml>=6
|
|
20
|
+
Requires-Dist: pathspec>=0.12
|
|
21
|
+
Requires-Dist: claude-agent-sdk>=0.2.101
|
|
22
|
+
Requires-Dist: openai-codex>=0.1.0b3
|
|
23
|
+
Requires-Dist: openai-codex-cli-bin>=0.137.0a4
|
|
24
|
+
Requires-Dist: github-copilot-sdk>=1.0.1
|
|
25
|
+
Requires-Python: >=3.14
|
|
26
|
+
Project-URL: Homepage, https://github.com/MarlzRana/aeview
|
|
27
|
+
Project-URL: Repository, https://github.com/MarlzRana/aeview
|
|
28
|
+
Project-URL: Issues, https://github.com/MarlzRana/aeview/issues
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# aeview
|
|
32
|
+
|
|
33
|
+
**Fan code reviewers across multiple AI agent harnesses, then merge one deduplicated verdict.**
|
|
34
|
+
|
|
35
|
+
aeview runs the *same* change past several reviewers — each a prompt you check into your repo —
|
|
36
|
+
across several agent harnesses (Claude Code, Codex, Copilot), in parallel. It collects every
|
|
37
|
+
finding, deduplicates them with an LLM judge, and writes a single `report.json` plus an exit code
|
|
38
|
+
you can loop on: `0` approve · `1` needs-attention · `2` error.
|
|
39
|
+
|
|
40
|
+
The bet: a *reviewer* is a versioned artifact (a prompt + the harnesses it runs on), and a panel of
|
|
41
|
+
independent models catches what any single model misses.
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
uv tool install aeview
|
|
45
|
+
cd your-repo
|
|
46
|
+
aeview run # review your current changes (auto mode); exit 1 if anything needs attention
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Contents
|
|
52
|
+
|
|
53
|
+
- [How it works](#how-it-works)
|
|
54
|
+
- [Requirements](#requirements)
|
|
55
|
+
- [Install](#install)
|
|
56
|
+
- [Quickstart](#quickstart)
|
|
57
|
+
- [Scopes — what to review](#scopes--what-to-review)
|
|
58
|
+
- [Reviewers](#reviewers)
|
|
59
|
+
- [Auto mode, activation & `.aeviewignore`](#auto-mode-activation--aeviewignore)
|
|
60
|
+
- [Harnesses](#harnesses)
|
|
61
|
+
- [Configuration](#configuration)
|
|
62
|
+
- [Commands](#commands)
|
|
63
|
+
- [The report & exit codes](#the-report--exit-codes)
|
|
64
|
+
- [Runs, lifecycle & output](#runs-lifecycle--output)
|
|
65
|
+
- [Development](#development)
|
|
66
|
+
- [License](#license)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## How it works
|
|
71
|
+
|
|
72
|
+
A **reviewer** is a prompt (`REVIEWER.md`) plus a set of **harness instances** (an agent + a model).
|
|
73
|
+
One `aeview run` does this:
|
|
74
|
+
|
|
75
|
+
1. **Resolve reviewers** — walk up from your cwd to home collecting `.aeview/reviewers/*`.
|
|
76
|
+
2. **Resolve the scope** — turn `--scope` into a concrete git diff (working tree, a branch, a PR, …).
|
|
77
|
+
3. **Bundle the diff** — small diffs are frozen inline; large ones hand the agent read-only git to
|
|
78
|
+
self-collect, so nothing is silently truncated.
|
|
79
|
+
4. **Fan out** — run every `reviewer × harness` pair concurrently, each in a **read-only** sandbox
|
|
80
|
+
(read anywhere, write nothing). Each emits findings against a fixed schema.
|
|
81
|
+
5. **Dedupe & merge** — an LLM judge groups duplicate findings across the panel; survivors are kept
|
|
82
|
+
verbatim with their provenance and an agreement count.
|
|
83
|
+
6. **Report** — write `report.json` and exit `0` / `1` / `2`.
|
|
84
|
+
|
|
85
|
+
Everything is persisted under `~/.aeview/runs/<id>/`, so a killed run can be `resume`d.
|
|
86
|
+
|
|
87
|
+
## Requirements
|
|
88
|
+
|
|
89
|
+
- **Python 3.14+** (the `uv` installer can fetch one for you).
|
|
90
|
+
- **macOS or Linux.**
|
|
91
|
+
- **Harness auth.** aeview drives each harness through its Python SDK, which **bundles a pinned CLI
|
|
92
|
+
binary** — you don't install Claude Code / Codex / Copilot separately. You *do* need to be
|
|
93
|
+
authenticated with each harness a reviewer uses. Run [`aeview doctor`](#commands) to see exactly
|
|
94
|
+
what's missing for the reviewers you have.
|
|
95
|
+
- **`gh`** (GitHub CLI) — for `--scope pr`, and to auto-detect a branch's base from its open PR.
|
|
96
|
+
Optional: aeview falls back to `origin/HEAD`, then `main`/`master`/`trunk`, when `gh` or a PR
|
|
97
|
+
isn't available.
|
|
98
|
+
|
|
99
|
+
## Install
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
uv tool install aeview # recommended
|
|
103
|
+
# or
|
|
104
|
+
pipx install aeview
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
> **Note — no special flags needed.** aeview currently depends on a *prerelease* Codex runtime
|
|
108
|
+
> (the Codex Python SDK is still in beta), so you'll see `openai-codex` / `openai-codex-cli-bin`
|
|
109
|
+
> alpha/beta versions in your install. Both `uv` and `pip` resolve these automatically because the
|
|
110
|
+
> prerelease markers are baked into aeview's own dependencies — you do **not** need
|
|
111
|
+
> `--prerelease=allow` or `--pre`. (Homebrew support is planned.)
|
|
112
|
+
|
|
113
|
+
After install, sanity-check your setup:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
aeview doctor
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Quickstart
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
cd your-repo
|
|
123
|
+
|
|
124
|
+
# Review your changes (auto mode: uncommitted work if the tree is dirty, else your branch vs base):
|
|
125
|
+
aeview run
|
|
126
|
+
|
|
127
|
+
# Preview the plan (roster + scope + bundle size) without spending anything:
|
|
128
|
+
aeview run --dry-run
|
|
129
|
+
|
|
130
|
+
# Review a branch against its base, with every reviewer you have:
|
|
131
|
+
aeview run --scope branch --reviewers all
|
|
132
|
+
|
|
133
|
+
# Get machine-readable output and act on the exit code:
|
|
134
|
+
aeview run --json && echo "approved" || echo "needs attention (or error)"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
A run prints a human summary (or `--json`), writes `report.json`, and exits with the verdict code.
|
|
138
|
+
|
|
139
|
+
## Scopes — what to review
|
|
140
|
+
|
|
141
|
+
`--scope <type>[:value]`. Omit `--scope` entirely for **`auto`**. Where a type takes a value, the
|
|
142
|
+
"bare" form (no `:value`) uses the default shown:
|
|
143
|
+
|
|
144
|
+
| Scope | Bare default | Reviews |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `working-tree` | — | all uncommitted changes |
|
|
147
|
+
| `staged` | — | only the staged changes |
|
|
148
|
+
| `branch[:base]` | base = auto | your branch vs `base` |
|
|
149
|
+
| `pr[:number]` | current branch's PR | a PR's diff (via `gh`) |
|
|
150
|
+
| `effective-pr[:base]` | base = auto | branch commits **+** uncommitted work, vs `base` |
|
|
151
|
+
| `commits[:a,b,c]` | `HEAD` | exactly the commits listed, each vs its own parent |
|
|
152
|
+
| `range:A..B` | *value required* | the diff between `A` and `B` |
|
|
153
|
+
| `patch:file` | *value required* | a diff file (or `-` for stdin) |
|
|
154
|
+
| `auto` | — | dirty → `working-tree`, else your branch vs base |
|
|
155
|
+
|
|
156
|
+
Notes:
|
|
157
|
+
|
|
158
|
+
- **`commits`** is a *set*, not a range: `--scope commits:a,c,e` reviews exactly those three commits,
|
|
159
|
+
each shown against its own parent (a union of per-commit patches). A single commit is just the
|
|
160
|
+
one-element case; bare `commits` is `HEAD`.
|
|
161
|
+
- **`--include-dirty`** folds uncommitted work onto a committed scope — use it with `branch`,
|
|
162
|
+
`auto`, or `staged`; it's a no-op on `working-tree`.
|
|
163
|
+
- **`--allow-conflicts`** reviews despite an in-progress merge/rebase (refused by default).
|
|
164
|
+
- Base resolution order: explicit value → the PR base → `origin/HEAD` → `main`/`master`/`trunk`.
|
|
165
|
+
|
|
166
|
+
## Reviewers
|
|
167
|
+
|
|
168
|
+
A reviewer lives at `.aeview/reviewers/<name>/REVIEWER.md`: YAML frontmatter + a prompt body.
|
|
169
|
+
|
|
170
|
+
```markdown
|
|
171
|
+
---
|
|
172
|
+
name: security
|
|
173
|
+
description: Hunts auth, injection, and trust-boundary bugs.
|
|
174
|
+
harnesses:
|
|
175
|
+
- { harness: claude-code, model: claude-opus-4-8 }
|
|
176
|
+
- { harness: codex, model: gpt-5.5, thinking: xhigh }
|
|
177
|
+
auto-activate-paths:
|
|
178
|
+
- "src/api/**"
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
You are a security reviewer. Find the injection, the auth gap, the unsafe
|
|
182
|
+
deserialization... (the rest of the prompt)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Frontmatter fields:
|
|
186
|
+
|
|
187
|
+
| Field | Required | Meaning |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `name` | yes | Must equal the directory name. |
|
|
190
|
+
| `description` | no | One line, shown by `aeview reviewers`. |
|
|
191
|
+
| `harnesses` | no | List of `{ harness, model, thinking? }`. **Omit** to use the global `fallbackReviewerHarnesses`. |
|
|
192
|
+
| `auto-activate-paths` | no | Globs that opt this reviewer into [auto mode](#auto-mode-activation--aeviewignore). |
|
|
193
|
+
|
|
194
|
+
### Resolution (walk-up)
|
|
195
|
+
|
|
196
|
+
aeview climbs from your cwd through its parent directories up to your home directory, looking for
|
|
197
|
+
`<dir>/.aeview/reviewers/<name>/REVIEWER.md`. **First match wins**, so a repo-local reviewer shadows
|
|
198
|
+
a personal one of the same name. Your home `~/.aeview/reviewers/` holds reviewers available
|
|
199
|
+
everywhere — including the seeded **`default`** reviewer (an adversarial general-purpose reviewer).
|
|
200
|
+
|
|
201
|
+
### Selecting reviewers
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
aeview run --reviewers security # one
|
|
205
|
+
aeview run --reviewers security,tests # several (comma-separated)
|
|
206
|
+
aeview run --reviewers security --reviewers tests # or repeated
|
|
207
|
+
aeview run --reviewers all # every reviewer visible here
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
With no `--reviewers`, aeview uses [auto mode](#auto-mode-activation--aeviewignore).
|
|
211
|
+
|
|
212
|
+
### Resource references
|
|
213
|
+
|
|
214
|
+
The reviewer's own directory (absolute path) is prepended to its prompt, so you can drop supporting
|
|
215
|
+
files beside `REVIEWER.md` (`references/checklist.md`, scripts, …) and reference them with relative
|
|
216
|
+
paths. Reviewers can read anywhere, so the links resolve.
|
|
217
|
+
|
|
218
|
+
### Scaffolding
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
aeview init security # create .aeview/reviewers/security/REVIEWER.md
|
|
222
|
+
aeview init security --with-harness # also scaffold a harnesses: block
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Auto mode, activation & `.aeviewignore`
|
|
226
|
+
|
|
227
|
+
**Auto mode** (no `--reviewers`) builds the roster as:
|
|
228
|
+
|
|
229
|
+
> **`default`** (always) **∪** every reviewer whose `auto-activate-paths` matches a changed file.
|
|
230
|
+
|
|
231
|
+
A reviewer with no `auto-activate-paths` never auto-runs (select it by name or with `all`). Matching
|
|
232
|
+
uses **literal globs** (Python's `PurePath.full_match`), anchored at the reviewer's `.aeview` parent
|
|
233
|
+
directory: a single `*` stops at `/`, `**` crosses directories, there's no negation, and it's
|
|
234
|
+
case-sensitive. So write `backend/**`, not `backend/`.
|
|
235
|
+
|
|
236
|
+
Auto-activation needs repo-root-relative paths, so `--scope patch` (and running outside a git repo)
|
|
237
|
+
runs only `default` — name any extra reviewers explicitly there.
|
|
238
|
+
|
|
239
|
+
**`.aeviewignore`** filters files **out of the diff before it's reviewed** — handy for lockfiles,
|
|
240
|
+
generated code, vendored trees. It uses faithful gitignore semantics (the `pathspec` library):
|
|
241
|
+
|
|
242
|
+
```gitignore
|
|
243
|
+
uv.lock
|
|
244
|
+
dist/
|
|
245
|
+
**/__snapshots__/
|
|
246
|
+
!important.generated.ts
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Files are collected on the same cwd→home walk (your home file is `~/.aeviewignore`); each file's
|
|
250
|
+
patterns anchor at its own directory, nearest rules win, and `!` negation is supported.
|
|
251
|
+
|
|
252
|
+
Like auto-activation, `.aeviewignore` is skipped for `--scope patch` (its paths aren't
|
|
253
|
+
repo-root-relative) — a patch is reviewed exactly as supplied.
|
|
254
|
+
|
|
255
|
+
## Harnesses
|
|
256
|
+
|
|
257
|
+
A harness instance is `{ harness, model, thinking? }`. Supported harnesses:
|
|
258
|
+
|
|
259
|
+
| `harness` | Driven via | Example `model` |
|
|
260
|
+
|---|---|---|
|
|
261
|
+
| `claude-code` | `claude-agent-sdk` | `claude-opus-4-8` |
|
|
262
|
+
| `codex` | `openai-codex` | `gpt-5.5` (e.g. `thinking: xhigh`) |
|
|
263
|
+
| `copilot` | `github-copilot-sdk` | a Copilot-served model |
|
|
264
|
+
|
|
265
|
+
Every harness runs **read-anywhere, write-nowhere**: a reviewer can read any file (to gather
|
|
266
|
+
context) but cannot modify your repo. Claude Code and Codex enforce this with their native
|
|
267
|
+
read-only sandboxes; Copilot uses a deny-by-default permission handler that only approves reads.
|
|
268
|
+
|
|
269
|
+
Each SDK ships a **pinned binary**, so aeview is insulated from your own CLI upgrades. To point a
|
|
270
|
+
harness at a different binary, set [`overrideHarnessBinaries`](#configuration).
|
|
271
|
+
|
|
272
|
+
## Configuration
|
|
273
|
+
|
|
274
|
+
Global settings live in `~/.aeview/settings.json`, seeded (write-if-absent) on first run. Its keys
|
|
275
|
+
are camelCase; the JSON run artifacts (`report.json`, `review.json`) use snake_case.
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"fallbackReviewerHarnesses": [
|
|
280
|
+
{ "harness": "claude-code", "model": "claude-opus-4-8" }
|
|
281
|
+
],
|
|
282
|
+
"deduplicationHarness": { "harness": "claude-code", "model": "claude-opus-4-8" },
|
|
283
|
+
"retention": { "keepLast": 20, "ttlDays": 14 },
|
|
284
|
+
"reviewTimeoutSeconds": 1200,
|
|
285
|
+
"overrideHarnessBinaries": { "codex": "/usr/local/bin/codex" }
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
| Key | Meaning |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `fallbackReviewerHarnesses` | Harnesses a reviewer runs on when its `REVIEWER.md` has no `harnesses:` block. |
|
|
292
|
+
| `deduplicationHarness` | The harness used to deduplicate findings across the panel. |
|
|
293
|
+
| `retention` | Auto-prune old runs: keep at least the newest `keepLast`, and drop runs that are *also* older than `ttlDays` days. |
|
|
294
|
+
| `reviewTimeoutSeconds` | Timeout (seconds) per harness attempt; transient errors retry, so a review's total time can exceed it. A timed-out review fails fast (no retry); `resume` re-runs it. |
|
|
295
|
+
| `overrideHarnessBinaries` | Optional per-harness override of the bundled CLI binary, by path. Keys: `claude-code`, `codex`, `copilot`. |
|
|
296
|
+
|
|
297
|
+
## Commands
|
|
298
|
+
|
|
299
|
+
| Command | What it does |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `aeview run` | Run reviewers over a scope; print the **gate** (verdict + findings, see below) and exit `0/1/2`. |
|
|
302
|
+
| `aeview status [run-id]` | Per-review progress + coverage (defaults to the latest run). `--wait` blocks to a terminal state and adopts its exit code. |
|
|
303
|
+
| `aeview result [run-id]` | Print a finished run's **full** report; exit with its `0/1/2` code. |
|
|
304
|
+
| `aeview resume <run-id>` | Re-run a run's non-`done` reviews against its frozen bundle, then re-merge. |
|
|
305
|
+
| `aeview list` | Recent runs, newest first: id, time, scope, verdict, coverage. |
|
|
306
|
+
| `aeview reviewers [name]` | List the reviewers visible here (walk-up), or show one's detail. |
|
|
307
|
+
| `aeview init <name>` | Scaffold a repo reviewer. `--with-harness` adds a `harnesses:` block. |
|
|
308
|
+
| `aeview doctor` | Preflight: reviewer config, harness binaries + auth, and `gh`. Exits 1 on failure. |
|
|
309
|
+
| `aeview version` | Print the version. |
|
|
310
|
+
|
|
311
|
+
Common `run` flags: `--scope`, `--reviewers`, `--include-dirty`, `--allow-conflicts`, `--dry-run`,
|
|
312
|
+
`--json`. Most commands accept `--json` for machine-readable output.
|
|
313
|
+
|
|
314
|
+
## The report & exit codes
|
|
315
|
+
|
|
316
|
+
The full merged artifact is `report.json` — what `aeview result` and the on-disk file give you:
|
|
317
|
+
|
|
318
|
+
```jsonc
|
|
319
|
+
{
|
|
320
|
+
"verdict": "needs-attention", // "approve" | "needs-attention"
|
|
321
|
+
"summary": "...",
|
|
322
|
+
"findings": [
|
|
323
|
+
{
|
|
324
|
+
"id": "f3", // stable run-local id assigned during merge
|
|
325
|
+
"title": "Unvalidated path used in file read",
|
|
326
|
+
"body": "...",
|
|
327
|
+
"severity": "high", // critical | high | medium | low
|
|
328
|
+
"category": "security", // bug | security | regression | test_gap | maintainability
|
|
329
|
+
"confidence": 0.9, // 0.0–1.0
|
|
330
|
+
"location": { "file": "src/api/files.py", "line_start": 42, "line_end": 48 },
|
|
331
|
+
"recommendation": "...",
|
|
332
|
+
"agreement": 2, // size of the dedup group (findings merged into this one)
|
|
333
|
+
"sources": [ // one entry per merged finding, with its originating review
|
|
334
|
+
{ "review": "security__codex-gpt-5.5", "severity": "high", "confidence": 0.9 },
|
|
335
|
+
{ "review": "security__claude-code-claude-opus-4-8", "severity": "high", "confidence": 0.85 }
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
],
|
|
339
|
+
"next_steps": [ { "source": "security__...", "steps": ["..."] } ],
|
|
340
|
+
"coverage": { "contributed": 3, "failed": 0 }, // reviews that completed vs. reviews that failed
|
|
341
|
+
"dedup": { "status": "ok", "harness": "...", "reason": null, "warning": null },
|
|
342
|
+
"usage": { "reviews": {...}, "dedup": {...}, "total": { "input_tokens": 0, "output_tokens": 0, "cost_usd": 0.0 } }
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**`aeview run` prints a *gate*, not the full report:** it's `report.json` with a top-level `run_id`
|
|
347
|
+
added and the result-only detail omitted — `findings[].id`, `next_steps`, `usage`, and the `dedup`
|
|
348
|
+
fields other than `status`. The kept fields keep their `report.json` names, so a consumer that reads
|
|
349
|
+
only the gate's fields works against both `run` and `result`. The dropped detail (token/cost
|
|
350
|
+
accounting, per-review next steps, dedup provenance, per-finding ids) lives in `aeview result`.
|
|
351
|
+
|
|
352
|
+
**Exit codes** (the loop-until-clean contract):
|
|
353
|
+
|
|
354
|
+
| Code | Meaning |
|
|
355
|
+
|---|---|
|
|
356
|
+
| `0` | **approve** — no actionable findings |
|
|
357
|
+
| `1` | **needs-attention** — at least one finding to act on |
|
|
358
|
+
| `2` | **error** — the run couldn't be trusted (e.g. *every* review failed) |
|
|
359
|
+
|
|
360
|
+
## Runs, lifecycle & output
|
|
361
|
+
|
|
362
|
+
Each run is a directory under `~/.aeview/runs/<id>/`:
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
runs/<id>/
|
|
366
|
+
run.json # the manifest: scope, roster, dedup plan, state, pid
|
|
367
|
+
bundle/ # the frozen diff under review
|
|
368
|
+
reviewers/<reviewer>/<instance>/
|
|
369
|
+
review.json # that review's findings + status + usage
|
|
370
|
+
review.log # raw harness-SDK event stream (JSONL)
|
|
371
|
+
dedup/<instance>/result.json # the dedup judge's grouping decision
|
|
372
|
+
report.json # the merged verdict
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
- **Timeout & fail-fast.** Each harness attempt is bounded by `reviewTimeoutSeconds`; a timed-out
|
|
376
|
+
review fails fast (timeouts aren't retried). A failed review is recorded — the run continues — and
|
|
377
|
+
`resume` re-runs it.
|
|
378
|
+
- **Crash recovery.** Runs record their pid; a crashed run is reconciled to `interrupted` and can be
|
|
379
|
+
`resume`d. `aeview status --wait` blocks until a run reaches a terminal state.
|
|
380
|
+
- **Retention.** On each `run`, terminal runs outside the newest `keepLast` *and* older than
|
|
381
|
+
`ttlDays` are pruned (`keepLast` is a guaranteed floor).
|
|
382
|
+
|
|
383
|
+
## Development
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
git clone https://github.com/MarlzRana/aeview
|
|
387
|
+
cd aeview
|
|
388
|
+
uv sync # install deps (incl. dev group)
|
|
389
|
+
uv run pytest # the offline test suite (no model calls)
|
|
390
|
+
uv run ruff check # lint
|
|
391
|
+
uv run pyright # type-check
|
|
392
|
+
uv run aeview --help
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
[MIT](LICENSE)
|