devin-qa-pack 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.
Files changed (36) hide show
  1. devin_qa_pack-0.1.0/LICENSE +21 -0
  2. devin_qa_pack-0.1.0/PKG-INFO +330 -0
  3. devin_qa_pack-0.1.0/README.md +316 -0
  4. devin_qa_pack-0.1.0/pyproject.toml +27 -0
  5. devin_qa_pack-0.1.0/setup.cfg +4 -0
  6. devin_qa_pack-0.1.0/src/devin_qa_pack/__init__.py +1 -0
  7. devin_qa_pack-0.1.0/src/devin_qa_pack/adapters/__init__.py +17 -0
  8. devin_qa_pack-0.1.0/src/devin_qa_pack/adapters/aider.py +91 -0
  9. devin_qa_pack-0.1.0/src/devin_qa_pack/adapters/base.py +26 -0
  10. devin_qa_pack-0.1.0/src/devin_qa_pack/adapters/claude_code.py +131 -0
  11. devin_qa_pack-0.1.0/src/devin_qa_pack/adapters/devin.py +28 -0
  12. devin_qa_pack-0.1.0/src/devin_qa_pack/claims.py +226 -0
  13. devin_qa_pack-0.1.0/src/devin_qa_pack/cli.py +354 -0
  14. devin_qa_pack-0.1.0/src/devin_qa_pack/html_report.py +193 -0
  15. devin_qa_pack-0.1.0/src/devin_qa_pack/intent.py +588 -0
  16. devin_qa_pack-0.1.0/src/devin_qa_pack/paths.py +46 -0
  17. devin_qa_pack-0.1.0/src/devin_qa_pack/report.py +171 -0
  18. devin_qa_pack-0.1.0/src/devin_qa_pack/session_end.py +262 -0
  19. devin_qa_pack-0.1.0/src/devin_qa_pack/verify.py +446 -0
  20. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/PKG-INFO +330 -0
  21. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/SOURCES.txt +34 -0
  22. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/dependency_links.txt +1 -0
  23. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/entry_points.txt +2 -0
  24. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/requires.txt +4 -0
  25. devin_qa_pack-0.1.0/src/devin_qa_pack.egg-info/top_level.txt +1 -0
  26. devin_qa_pack-0.1.0/tests/test_adapters.py +178 -0
  27. devin_qa_pack-0.1.0/tests/test_claims.py +128 -0
  28. devin_qa_pack-0.1.0/tests/test_cli.py +126 -0
  29. devin_qa_pack-0.1.0/tests/test_html_report.py +57 -0
  30. devin_qa_pack-0.1.0/tests/test_intent.py +376 -0
  31. devin_qa_pack-0.1.0/tests/test_offline_core.py +69 -0
  32. devin_qa_pack-0.1.0/tests/test_paths.py +23 -0
  33. devin_qa_pack-0.1.0/tests/test_report.py +93 -0
  34. devin_qa_pack-0.1.0/tests/test_session_end.py +195 -0
  35. devin_qa_pack-0.1.0/tests/test_smoke.py +4 -0
  36. devin_qa_pack-0.1.0/tests/test_verify.py +265 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Icaro0310
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,330 @@
1
+ Metadata-Version: 2.4
2
+ Name: devin-qa-pack
3
+ Version: 0.1.0
4
+ Summary: QA audit for Devin sessions: verifies deliverable claims (tests, commits, files, pushes) against tool_call_state ground truth.
5
+ Author: Icaro0310
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: devin-internals-spec<0.4.0,>=0.3.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=8; extra == "dev"
13
+ Dynamic: license-file
14
+
15
+ <div align="center">
16
+
17
+ <img src="assets/banner.svg" alt="devin-qa-pack" width="100%"/>
18
+
19
+ <a href="https://github.com/Icaro0310/devin-qa-pack/actions/workflows/ci.yml"><img src="https://github.com/Icaro0310/devin-qa-pack/actions/workflows/ci.yml/badge.svg" alt="CI"/></a>
20
+ <a href="https://github.com/Icaro0310/devin-qa-pack/releases"><img src="https://img.shields.io/github/v/release/Icaro0310/devin-qa-pack" alt="GitHub release"/></a>
21
+ <a href="https://scorecard.dev/viewer/?uri=github.com/Icaro0310/devin-qa-pack"><img src="https://api.scorecard.dev/projects/github.com/Icaro0310/devin-qa-pack/badge" alt="OpenSSF Scorecard"/></a>
22
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT"/></a>
23
+ <img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python 3.10+"/>
24
+
25
+
26
+ </div>
27
+
28
+ # devin-qa-pack
29
+
30
+ > **Unofficial community project.** Not affiliated with, endorsed by, or
31
+ > sponsored by Cognition AI. "Devin" is a trademark of Cognition AI.
32
+
33
+ **[Linux](README.linux.md)** · **[Personal Windows](README.windows.md)** · **[Corporate Windows](README.corporate-windows.md)**
34
+
35
+ Part of the [awesome-devin](https://github.com/Icaro0310/awesome-devin) ecosystem: the curated hub for the devin-* tools.
36
+
37
+ Flagship QA audit for Devin sessions: checks that what a session *claims* it
38
+ delivered is backed by what its tool calls *actually did* — tests run,
39
+ commits created, files written, work pushed, HTTP statuses returned —
40
+ and prints a verdict per session: `PASS` / `PARTIAL` / `UNVERIFIED`.
41
+
42
+ ## The problem
43
+
44
+ Devin sessions end with the agent saying "tests passed", "committed
45
+ `a1b2c3d`", "pushed to origin". Those are text claims — a model can write
46
+ them whether or not the actions happened. Verifying them today means
47
+ scrolling the transcript by hand or trusting the summary. Teams that
48
+ adopt agent workflows need a cheap, repeatable way to answer *did this
49
+ session actually do what it claims?*
50
+
51
+ ## Prior art
52
+
53
+ Transcript/session viewers (including Devin's own UI) show *what
54
+ happened*; CI status checks verify outcomes after the fact; neither
55
+ cross-checks the agent's delivery claims against recorded actions. The
56
+ general idea — compare declared intent with observed behavior — is old
57
+ (manifest-vs-manifest audits, `git fsck`, attestations like SLSA
58
+ provenance). What didn't exist: applying it to an agent's claims vs. its
59
+ own persisted tool-call log.
60
+
61
+ ## What makes it Devin-native
62
+
63
+ Devin persists every tool call in `sessions.db → tool_call_state`. This
64
+ tool reads that table via
65
+ [devin-internals-spec](https://github.com/Icaro0310/devin-internals-spec)
66
+ and treats it as **ground truth**: a "tests passed" claim must be backed
67
+ by a run/execute call that ran a test runner and completed; "committed
68
+ `sha`" must show the hash in a call or in `git log`. Text-only auditors
69
+ *cannot* do this — remove Devin's store and the check disappears.
70
+
71
+ ## Install
72
+
73
+ Python ≥ 3.10 and `pipx` are required. **Windows (PowerShell):** install `pipx` with `py -m pip install --user pipx`, run `py -m pipx ensurepath`, then reopen the terminal. **Linux (Debian/Ubuntu):** run `sudo apt install pipx python3-venv` and `pipx ensurepath`; reopen the terminal. Other Linux distributions should install `pipx` using their package manager.
74
+
75
+ ```bash
76
+ # one-liner installer (pipx preferred, pip --user fallback)
77
+ curl -fsSL https://raw.githubusercontent.com/Icaro0310/devin-qa-pack/main/install.sh | sh
78
+
79
+ # or directly
80
+ pipx install "devin-qa-pack @ git+https://github.com/Icaro0310/devin-qa-pack.git"
81
+ ```
82
+
83
+ [GitHub Releases](https://github.com/Icaro0310/devin-qa-pack/releases)
84
+ ship the wheel, sdist and CycloneDX SBOM per tag.
85
+
86
+ ## Usage
87
+
88
+ ```bash
89
+ # audit one session (exact id or unique prefix)
90
+ devin-qa-pack audit --session <id> --sessions-db path/to/sessions.db
91
+
92
+ # audit everything, most recent first
93
+ devin-qa-pack audit --all --limit 20 --json
94
+
95
+ # aggregated report: one self-contained static HTML file (inline CSS,
96
+ # no JS, no external assets — opens offline)
97
+ devin-qa-pack report --sessions-db path/to/sessions.db --out report.html
98
+
99
+ # live audit at SessionEnd: audit ONLY the session that just ended
100
+ # (hook mode — writes a JSON side file, never touches the session)
101
+ devin-qa-pack session-end
102
+
103
+ # intent vs. coverage (QA-4): did the agent touch what the prompt named?
104
+ devin-qa-pack intent <session> --sessions-db path/to/sessions.db
105
+
106
+ # audit a foreign transcript instead of sessions.db (experimental)
107
+ devin-qa-pack audit --transcript .aider.chat.history.md
108
+ devin-qa-pack audit --transcript ~/.claude/projects/<slug>/<id>.jsonl
109
+ ```
110
+
111
+ Real output, on the synthetic fixture from the quick start:
112
+
113
+ ```text
114
+ UNVERIFIED sess-unverifiable Mystery session — 1 claim(s): 0 verified, 0 disputed, 1 unverifiable
115
+ [unverifiable] file/docs/spec.pdf: no matching tool call and working dir not on disk
116
+ PARTIAL sess-disputed Disputed session — 2 claim(s): 0 verified, 2 disputed, 0 unverifiable
117
+ [disputed ] tests/tests: no execute call matching `tests` recorded
118
+ [disputed ] commit/deadbee: no commit call recorded and no repo on disk to check
119
+ PASS sess-verified Verified session — 4 claim(s): 4 verified, 0 disputed, 0 unverifiable
120
+ [verified ] tests/pytest: `python -m pytest -q` completed (tc-pytest)
121
+ [verified ] commit/a1b2c3d: `git commit -m fix` completed (tc-commit)
122
+ [verified ] push/push: `git push origin main` completed (tc-push)
123
+ [verified ] file/src/report.html: tool call tc-write completed
124
+ ```
125
+
126
+ Recorded as an asciicast: [assets/demo.cast](assets/demo.cast) —
127
+ `asciinema play demo.cast`.
128
+
129
+ The `report` subcommand audits all sessions (or one with `--session`,
130
+ bounded with `--limit`) and writes a single deterministic HTML file:
131
+ verdict counts, a per-session table and a per-claim breakdown with
132
+ evidence and the source excerpt for every checked claim.
133
+
134
+ `--sessions-db` may be omitted. It auto-detects
135
+ `%APPDATA%/devin/cli/sessions.db` on Windows and
136
+ `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (default
137
+ `~/.local/share/devin/cli/sessions.db`). Always read-only.
138
+
139
+ No Devin installed? Try it on a synthetic fixture:
140
+
141
+ ```bash
142
+ pipx install "devin-internals-spec==0.3.0"
143
+ devin-inspect make-fixture /tmp/fx
144
+ devin-qa-pack audit --all --sessions-db /tmp/fx/cli/sessions.db
145
+ ```
146
+
147
+ Exit codes: `0` every session `PASS` · `1` some session
148
+ `PARTIAL`/`UNVERIFIED` · `2` audit could not run.
149
+
150
+ ## Intent vs. coverage (`intent`, QA-4)
151
+
152
+ `devin-qa-pack intent <session>` answers a different question: did the
153
+ agent actually touch what the user asked for? It takes the session's
154
+ **first user message**, extracts the paths/modules/repo names it
155
+ references, extracts every path seen in `tool_call_state` payloads
156
+ (writes, reads and commands all count as "touched") and reports two
157
+ heuristic findings:
158
+
159
+ - **`possibly_missed`** — paths the prompt explicitly named (filename
160
+ with an extension, absolute or `./`-prefixed path) that no tool call
161
+ ever referenced.
162
+ - **`scope_drift`** — touched paths sharing no directory, filename or
163
+ repo anchor with anything the prompt named.
164
+
165
+ Statuses: `aligned` (nothing flagged) · `flagged` (at least one missed
166
+ or drift path) · `skipped` (not computable — no user message, no
167
+ path-ish references in the prompt, or no tool calls). Exit codes:
168
+ `0` aligned · `1` flagged or skipped · `2` could not run. The same
169
+ analysis rides along as an `intent` field in the `session-end` side
170
+ file whenever the session resolves.
171
+
172
+ **This is a heuristic** — kept deliberately conservative: only
173
+ file-grade references can be "missed" (a bare `src/` mention or a
174
+ slash-word like `and/or` never is); coverage is by path-segment and
175
+ basename match, not semantics; and drift means *"no prompt-named
176
+ anchor"*, not *"wrong file"*. A prompt naming no paths at all yields
177
+ `skipped` rather than flagging every touched file.
178
+
179
+ ## SessionEnd hook (live audit)
180
+
181
+ `devin-qa-pack session-end` audits **only the session that just ended**
182
+ and writes the verdict to a JSON **side file** — never into the
183
+ transcript or any Devin store. Session resolution order:
184
+
185
+ 1. `--session-id <id>` (exact id or unique prefix)
186
+ 2. the `session_id` field of the hook payload JSON on stdin
187
+ 3. the `DEVIN_SESSION_ID` env var (exported by the hook dispatcher)
188
+ 4. the most recently active session in `sessions.db`
189
+
190
+ The side file defaults to `<data-dir>/qa/<session-id>.json` (same
191
+ platform data dir as the store auto-detection; `--data-dir` and `--out`
192
+ override) and contains `{session_id, verdict, claims: [...],
193
+ audited_at}` — the same claim shape as `audit --json`, plus an
194
+ optional `intent` field (the QA-4 prompt-vs-touched-paths analysis)
195
+ when the session resolves. A one-line
196
+ summary is also printed. `--limit N` bounds the number of claims
197
+ verified.
198
+
199
+ **Fail-soft:** `session-end` always exits `0` once it ran — the verdict
200
+ travels in the side file, so a hook can never fail the host session. A
201
+ session that cannot be resolved produces a `SKIPPED` verdict (still
202
+ written to the side file when an id is known). Non-zero exits are
203
+ reserved for usage errors (`2`), consistent with the other subcommands.
204
+
205
+ Register it as a `SessionEnd` hook (hooks.json entry for the
206
+ `devin-powerups` hook dispatcher — it pipes the hook payload JSON on
207
+ stdin and exports `DEVIN_SESSION_ID`):
208
+
209
+ ```json
210
+ {
211
+ "SessionEnd": [
212
+ {
213
+ "matcher": "",
214
+ "hooks": [
215
+ {
216
+ "type": "command",
217
+ "command": "devin-qa-pack session-end",
218
+ "timeout": 30
219
+ }
220
+ ]
221
+ }
222
+ ]
223
+ }
224
+ ```
225
+
226
+ ## Auditing other agents (experimental)
227
+
228
+ `audit --transcript` runs the same claim/evidence model over non-Devin
229
+ transcripts via the adapters in `src/devin_qa_pack/adapters/`:
230
+
231
+ - **`aider`** — `.aider.chat.history.md`. `> /run` and `> /test` records
232
+ become execute calls with `unknown` status (the history does not store
233
+ exit codes), so test claims resolve `unverifiable`; commit claims are
234
+ checked against `git log` in the working directory.
235
+ - **`claude-code`** — session `.jsonl` transcripts. `Bash` → execute,
236
+ `Write`/`Edit`/`MultiEdit`/`NotebookEdit` → write, `tool_result`
237
+ blocks mark calls completed/failed.
238
+
239
+ `--format` overrides extension-based detection; `--cwd` sets the
240
+ directory used for git/file checks. These adapters are experimental —
241
+ formats outside the recorded subsets degrade to `UNVERIFIED`, never to
242
+ a false `PASS`.
243
+
244
+ ## Works with Devin alone (Devin-only mode)
245
+
246
+ devin-qa-pack is an offline, read-only audit of recorded Devin sessions. It
247
+ never calls an LLM, never touches the network, and never writes to Devin's
248
+ stores — a safe pick for restricted machines.
249
+
250
+ ## Platform support
251
+
252
+ Tested on **Windows and Linux** (`windows-latest` + `ubuntu-latest` in CI).
253
+ The CLI session DB is auto-detected from `%APPDATA%/devin/cli/sessions.db`
254
+ on Windows and `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (default
255
+ `~/.local/share/devin/cli/sessions.db`). A legacy `~/.config/devin` layout is
256
+ also checked. macOS uses `~/Library/Application Support/devin/`. Pass
257
+ `--sessions-db` to override.
258
+
259
+
260
+ `--online` (QA-2, opt-in) enables live HEAD checks of deploy/URL claims
261
+ ("deployed to https://…"), and only against `--allow-domain` hosts —
262
+ network is off by default and the audit is fully offline otherwise.
263
+
264
+ ## Limitations
265
+
266
+ - `chat_message` and `tool_call_*_json` payloads are **unstable** formats
267
+ (see devin-internals-spec SCHEMA.md). Decoding is defensive; rows that
268
+ can't be read resolve claims to `unverifiable`, never to `disputed`.
269
+ - Claim extraction is heuristic: it looks for delivery phrasing
270
+ ("tests passed", "committed <sha>", "created <path>", "pushed",
271
+ "the API returned 200"). Claims phrased differently are not
272
+ extracted — the audit then reports `UNVERIFIED`, not a false `PASS`.
273
+ - HTTP-status claims are checked only against recorded tool-call
274
+ output: a claim is `verified` when a recorded status matches,
275
+ `disputed` when outputs record a different status and `unverifiable`
276
+ when no output records any status. No request is ever replayed.
277
+ - File/commit checks use `sessions.working_directory` only when it
278
+ exists on disk and is a git repo — otherwise they rely on tool-call
279
+ evidence alone.
280
+ - The `intent` analysis is explicitly heuristic: prompt path extraction
281
+ is regex-based (bare directory mentions without extensions and
282
+ extensionless `a/b` tokens can be missed as references), "touched"
283
+ includes reads and commands not just writes, and later user
284
+ follow-ups are ignored — only the first user message sets intent.
285
+ Treat `possibly_missed`/`scope_drift` as review hints, not verdicts.
286
+ - The transcript adapters cover a subset of Aider/Claude Code formats:
287
+ aider's history cannot prove a `/run` succeeded (no exit codes), and
288
+ unrecognized tool names become `other` — still searchable evidence,
289
+ but weak. Real-world transcripts that differ degrade to
290
+ `UNVERIFIED`.
291
+ - It verifies *that* actions happened, not that the work is good.
292
+ Green tests in a tool call don't prove the fix is correct.
293
+ - Read-only, offline; no real-time monitoring, no MCP server (M2).
294
+
295
+ ## Development
296
+
297
+ ```bash
298
+ pip install -e ".[dev]"
299
+ python -m pytest
300
+ ```
301
+
302
+ ## When to use this
303
+
304
+ - You want to verify that a finished Devin session actually ran tests, created commits, wrote files, or pushed — not just claimed to.
305
+ - You are gating agent output in CI and need a machine-readable verdict (`PASS`/`PARTIAL`/`UNVERIFIED`) with exit codes.
306
+ - You want to audit many sessions at once, offline, without sending transcripts to an LLM — and optionally publish a single static HTML report (`devin-qa-pack report`).
307
+ - You are on a restricted machine: the tool is read-only and never touches the network.
308
+
309
+ ## When NOT to use this
310
+
311
+ - You need a review of code quality or correctness — it verifies that actions happened, not that the work is good.
312
+ - You need real-time monitoring or an MCP server (on the M2 roadmap).
313
+ - Your agent is not Devin — the ground truth comes from Devin's `sessions.db`.
314
+
315
+ ## FAQ
316
+
317
+ **How do I verify a Devin session actually ran the tests it claims?** Run `devin-qa-pack audit --session <id>`. It reads the session's `tool_call_state` rows from `sessions.db`, extracts delivery claims like "tests passed", and checks each against recorded tool calls — a claim without matching evidence resolves to `UNVERIFIED` or `PARTIAL`, not `PASS`.
318
+
319
+ **Does devin-qa-pack need network access or an API key?** No. It is a fully offline, read-only audit of the local `sessions.db`. It never calls an LLM, never sends data anywhere, and never writes to Devin's stores.
320
+
321
+ **Where does devin-qa-pack find sessions.db?** It auto-detects `%APPDATA%/devin/cli/sessions.db` on Windows, `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (`~/.local/share/devin/cli/sessions.db` by default), `~/Library/Application Support/devin/` on macOS, plus a legacy `~/.config/devin` layout. Override with `--sessions-db`.
322
+
323
+ ## License
324
+
325
+ MIT — see [LICENSE](LICENSE).
326
+
327
+
328
+ ---
329
+
330
+ If this saved you debugging time, a ⭐ on the repo helps others find it.
@@ -0,0 +1,316 @@
1
+ <div align="center">
2
+
3
+ <img src="assets/banner.svg" alt="devin-qa-pack" width="100%"/>
4
+
5
+ <a href="https://github.com/Icaro0310/devin-qa-pack/actions/workflows/ci.yml"><img src="https://github.com/Icaro0310/devin-qa-pack/actions/workflows/ci.yml/badge.svg" alt="CI"/></a>
6
+ <a href="https://github.com/Icaro0310/devin-qa-pack/releases"><img src="https://img.shields.io/github/v/release/Icaro0310/devin-qa-pack" alt="GitHub release"/></a>
7
+ <a href="https://scorecard.dev/viewer/?uri=github.com/Icaro0310/devin-qa-pack"><img src="https://api.scorecard.dev/projects/github.com/Icaro0310/devin-qa-pack/badge" alt="OpenSSF Scorecard"/></a>
8
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT"/></a>
9
+ <img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python 3.10+"/>
10
+
11
+
12
+ </div>
13
+
14
+ # devin-qa-pack
15
+
16
+ > **Unofficial community project.** Not affiliated with, endorsed by, or
17
+ > sponsored by Cognition AI. "Devin" is a trademark of Cognition AI.
18
+
19
+ **[Linux](README.linux.md)** · **[Personal Windows](README.windows.md)** · **[Corporate Windows](README.corporate-windows.md)**
20
+
21
+ Part of the [awesome-devin](https://github.com/Icaro0310/awesome-devin) ecosystem: the curated hub for the devin-* tools.
22
+
23
+ Flagship QA audit for Devin sessions: checks that what a session *claims* it
24
+ delivered is backed by what its tool calls *actually did* — tests run,
25
+ commits created, files written, work pushed, HTTP statuses returned —
26
+ and prints a verdict per session: `PASS` / `PARTIAL` / `UNVERIFIED`.
27
+
28
+ ## The problem
29
+
30
+ Devin sessions end with the agent saying "tests passed", "committed
31
+ `a1b2c3d`", "pushed to origin". Those are text claims — a model can write
32
+ them whether or not the actions happened. Verifying them today means
33
+ scrolling the transcript by hand or trusting the summary. Teams that
34
+ adopt agent workflows need a cheap, repeatable way to answer *did this
35
+ session actually do what it claims?*
36
+
37
+ ## Prior art
38
+
39
+ Transcript/session viewers (including Devin's own UI) show *what
40
+ happened*; CI status checks verify outcomes after the fact; neither
41
+ cross-checks the agent's delivery claims against recorded actions. The
42
+ general idea — compare declared intent with observed behavior — is old
43
+ (manifest-vs-manifest audits, `git fsck`, attestations like SLSA
44
+ provenance). What didn't exist: applying it to an agent's claims vs. its
45
+ own persisted tool-call log.
46
+
47
+ ## What makes it Devin-native
48
+
49
+ Devin persists every tool call in `sessions.db → tool_call_state`. This
50
+ tool reads that table via
51
+ [devin-internals-spec](https://github.com/Icaro0310/devin-internals-spec)
52
+ and treats it as **ground truth**: a "tests passed" claim must be backed
53
+ by a run/execute call that ran a test runner and completed; "committed
54
+ `sha`" must show the hash in a call or in `git log`. Text-only auditors
55
+ *cannot* do this — remove Devin's store and the check disappears.
56
+
57
+ ## Install
58
+
59
+ Python ≥ 3.10 and `pipx` are required. **Windows (PowerShell):** install `pipx` with `py -m pip install --user pipx`, run `py -m pipx ensurepath`, then reopen the terminal. **Linux (Debian/Ubuntu):** run `sudo apt install pipx python3-venv` and `pipx ensurepath`; reopen the terminal. Other Linux distributions should install `pipx` using their package manager.
60
+
61
+ ```bash
62
+ # one-liner installer (pipx preferred, pip --user fallback)
63
+ curl -fsSL https://raw.githubusercontent.com/Icaro0310/devin-qa-pack/main/install.sh | sh
64
+
65
+ # or directly
66
+ pipx install "devin-qa-pack @ git+https://github.com/Icaro0310/devin-qa-pack.git"
67
+ ```
68
+
69
+ [GitHub Releases](https://github.com/Icaro0310/devin-qa-pack/releases)
70
+ ship the wheel, sdist and CycloneDX SBOM per tag.
71
+
72
+ ## Usage
73
+
74
+ ```bash
75
+ # audit one session (exact id or unique prefix)
76
+ devin-qa-pack audit --session <id> --sessions-db path/to/sessions.db
77
+
78
+ # audit everything, most recent first
79
+ devin-qa-pack audit --all --limit 20 --json
80
+
81
+ # aggregated report: one self-contained static HTML file (inline CSS,
82
+ # no JS, no external assets — opens offline)
83
+ devin-qa-pack report --sessions-db path/to/sessions.db --out report.html
84
+
85
+ # live audit at SessionEnd: audit ONLY the session that just ended
86
+ # (hook mode — writes a JSON side file, never touches the session)
87
+ devin-qa-pack session-end
88
+
89
+ # intent vs. coverage (QA-4): did the agent touch what the prompt named?
90
+ devin-qa-pack intent <session> --sessions-db path/to/sessions.db
91
+
92
+ # audit a foreign transcript instead of sessions.db (experimental)
93
+ devin-qa-pack audit --transcript .aider.chat.history.md
94
+ devin-qa-pack audit --transcript ~/.claude/projects/<slug>/<id>.jsonl
95
+ ```
96
+
97
+ Real output, on the synthetic fixture from the quick start:
98
+
99
+ ```text
100
+ UNVERIFIED sess-unverifiable Mystery session — 1 claim(s): 0 verified, 0 disputed, 1 unverifiable
101
+ [unverifiable] file/docs/spec.pdf: no matching tool call and working dir not on disk
102
+ PARTIAL sess-disputed Disputed session — 2 claim(s): 0 verified, 2 disputed, 0 unverifiable
103
+ [disputed ] tests/tests: no execute call matching `tests` recorded
104
+ [disputed ] commit/deadbee: no commit call recorded and no repo on disk to check
105
+ PASS sess-verified Verified session — 4 claim(s): 4 verified, 0 disputed, 0 unverifiable
106
+ [verified ] tests/pytest: `python -m pytest -q` completed (tc-pytest)
107
+ [verified ] commit/a1b2c3d: `git commit -m fix` completed (tc-commit)
108
+ [verified ] push/push: `git push origin main` completed (tc-push)
109
+ [verified ] file/src/report.html: tool call tc-write completed
110
+ ```
111
+
112
+ Recorded as an asciicast: [assets/demo.cast](assets/demo.cast) —
113
+ `asciinema play demo.cast`.
114
+
115
+ The `report` subcommand audits all sessions (or one with `--session`,
116
+ bounded with `--limit`) and writes a single deterministic HTML file:
117
+ verdict counts, a per-session table and a per-claim breakdown with
118
+ evidence and the source excerpt for every checked claim.
119
+
120
+ `--sessions-db` may be omitted. It auto-detects
121
+ `%APPDATA%/devin/cli/sessions.db` on Windows and
122
+ `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (default
123
+ `~/.local/share/devin/cli/sessions.db`). Always read-only.
124
+
125
+ No Devin installed? Try it on a synthetic fixture:
126
+
127
+ ```bash
128
+ pipx install "devin-internals-spec==0.3.0"
129
+ devin-inspect make-fixture /tmp/fx
130
+ devin-qa-pack audit --all --sessions-db /tmp/fx/cli/sessions.db
131
+ ```
132
+
133
+ Exit codes: `0` every session `PASS` · `1` some session
134
+ `PARTIAL`/`UNVERIFIED` · `2` audit could not run.
135
+
136
+ ## Intent vs. coverage (`intent`, QA-4)
137
+
138
+ `devin-qa-pack intent <session>` answers a different question: did the
139
+ agent actually touch what the user asked for? It takes the session's
140
+ **first user message**, extracts the paths/modules/repo names it
141
+ references, extracts every path seen in `tool_call_state` payloads
142
+ (writes, reads and commands all count as "touched") and reports two
143
+ heuristic findings:
144
+
145
+ - **`possibly_missed`** — paths the prompt explicitly named (filename
146
+ with an extension, absolute or `./`-prefixed path) that no tool call
147
+ ever referenced.
148
+ - **`scope_drift`** — touched paths sharing no directory, filename or
149
+ repo anchor with anything the prompt named.
150
+
151
+ Statuses: `aligned` (nothing flagged) · `flagged` (at least one missed
152
+ or drift path) · `skipped` (not computable — no user message, no
153
+ path-ish references in the prompt, or no tool calls). Exit codes:
154
+ `0` aligned · `1` flagged or skipped · `2` could not run. The same
155
+ analysis rides along as an `intent` field in the `session-end` side
156
+ file whenever the session resolves.
157
+
158
+ **This is a heuristic** — kept deliberately conservative: only
159
+ file-grade references can be "missed" (a bare `src/` mention or a
160
+ slash-word like `and/or` never is); coverage is by path-segment and
161
+ basename match, not semantics; and drift means *"no prompt-named
162
+ anchor"*, not *"wrong file"*. A prompt naming no paths at all yields
163
+ `skipped` rather than flagging every touched file.
164
+
165
+ ## SessionEnd hook (live audit)
166
+
167
+ `devin-qa-pack session-end` audits **only the session that just ended**
168
+ and writes the verdict to a JSON **side file** — never into the
169
+ transcript or any Devin store. Session resolution order:
170
+
171
+ 1. `--session-id <id>` (exact id or unique prefix)
172
+ 2. the `session_id` field of the hook payload JSON on stdin
173
+ 3. the `DEVIN_SESSION_ID` env var (exported by the hook dispatcher)
174
+ 4. the most recently active session in `sessions.db`
175
+
176
+ The side file defaults to `<data-dir>/qa/<session-id>.json` (same
177
+ platform data dir as the store auto-detection; `--data-dir` and `--out`
178
+ override) and contains `{session_id, verdict, claims: [...],
179
+ audited_at}` — the same claim shape as `audit --json`, plus an
180
+ optional `intent` field (the QA-4 prompt-vs-touched-paths analysis)
181
+ when the session resolves. A one-line
182
+ summary is also printed. `--limit N` bounds the number of claims
183
+ verified.
184
+
185
+ **Fail-soft:** `session-end` always exits `0` once it ran — the verdict
186
+ travels in the side file, so a hook can never fail the host session. A
187
+ session that cannot be resolved produces a `SKIPPED` verdict (still
188
+ written to the side file when an id is known). Non-zero exits are
189
+ reserved for usage errors (`2`), consistent with the other subcommands.
190
+
191
+ Register it as a `SessionEnd` hook (hooks.json entry for the
192
+ `devin-powerups` hook dispatcher — it pipes the hook payload JSON on
193
+ stdin and exports `DEVIN_SESSION_ID`):
194
+
195
+ ```json
196
+ {
197
+ "SessionEnd": [
198
+ {
199
+ "matcher": "",
200
+ "hooks": [
201
+ {
202
+ "type": "command",
203
+ "command": "devin-qa-pack session-end",
204
+ "timeout": 30
205
+ }
206
+ ]
207
+ }
208
+ ]
209
+ }
210
+ ```
211
+
212
+ ## Auditing other agents (experimental)
213
+
214
+ `audit --transcript` runs the same claim/evidence model over non-Devin
215
+ transcripts via the adapters in `src/devin_qa_pack/adapters/`:
216
+
217
+ - **`aider`** — `.aider.chat.history.md`. `> /run` and `> /test` records
218
+ become execute calls with `unknown` status (the history does not store
219
+ exit codes), so test claims resolve `unverifiable`; commit claims are
220
+ checked against `git log` in the working directory.
221
+ - **`claude-code`** — session `.jsonl` transcripts. `Bash` → execute,
222
+ `Write`/`Edit`/`MultiEdit`/`NotebookEdit` → write, `tool_result`
223
+ blocks mark calls completed/failed.
224
+
225
+ `--format` overrides extension-based detection; `--cwd` sets the
226
+ directory used for git/file checks. These adapters are experimental —
227
+ formats outside the recorded subsets degrade to `UNVERIFIED`, never to
228
+ a false `PASS`.
229
+
230
+ ## Works with Devin alone (Devin-only mode)
231
+
232
+ devin-qa-pack is an offline, read-only audit of recorded Devin sessions. It
233
+ never calls an LLM, never touches the network, and never writes to Devin's
234
+ stores — a safe pick for restricted machines.
235
+
236
+ ## Platform support
237
+
238
+ Tested on **Windows and Linux** (`windows-latest` + `ubuntu-latest` in CI).
239
+ The CLI session DB is auto-detected from `%APPDATA%/devin/cli/sessions.db`
240
+ on Windows and `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (default
241
+ `~/.local/share/devin/cli/sessions.db`). A legacy `~/.config/devin` layout is
242
+ also checked. macOS uses `~/Library/Application Support/devin/`. Pass
243
+ `--sessions-db` to override.
244
+
245
+
246
+ `--online` (QA-2, opt-in) enables live HEAD checks of deploy/URL claims
247
+ ("deployed to https://…"), and only against `--allow-domain` hosts —
248
+ network is off by default and the audit is fully offline otherwise.
249
+
250
+ ## Limitations
251
+
252
+ - `chat_message` and `tool_call_*_json` payloads are **unstable** formats
253
+ (see devin-internals-spec SCHEMA.md). Decoding is defensive; rows that
254
+ can't be read resolve claims to `unverifiable`, never to `disputed`.
255
+ - Claim extraction is heuristic: it looks for delivery phrasing
256
+ ("tests passed", "committed <sha>", "created <path>", "pushed",
257
+ "the API returned 200"). Claims phrased differently are not
258
+ extracted — the audit then reports `UNVERIFIED`, not a false `PASS`.
259
+ - HTTP-status claims are checked only against recorded tool-call
260
+ output: a claim is `verified` when a recorded status matches,
261
+ `disputed` when outputs record a different status and `unverifiable`
262
+ when no output records any status. No request is ever replayed.
263
+ - File/commit checks use `sessions.working_directory` only when it
264
+ exists on disk and is a git repo — otherwise they rely on tool-call
265
+ evidence alone.
266
+ - The `intent` analysis is explicitly heuristic: prompt path extraction
267
+ is regex-based (bare directory mentions without extensions and
268
+ extensionless `a/b` tokens can be missed as references), "touched"
269
+ includes reads and commands not just writes, and later user
270
+ follow-ups are ignored — only the first user message sets intent.
271
+ Treat `possibly_missed`/`scope_drift` as review hints, not verdicts.
272
+ - The transcript adapters cover a subset of Aider/Claude Code formats:
273
+ aider's history cannot prove a `/run` succeeded (no exit codes), and
274
+ unrecognized tool names become `other` — still searchable evidence,
275
+ but weak. Real-world transcripts that differ degrade to
276
+ `UNVERIFIED`.
277
+ - It verifies *that* actions happened, not that the work is good.
278
+ Green tests in a tool call don't prove the fix is correct.
279
+ - Read-only, offline; no real-time monitoring, no MCP server (M2).
280
+
281
+ ## Development
282
+
283
+ ```bash
284
+ pip install -e ".[dev]"
285
+ python -m pytest
286
+ ```
287
+
288
+ ## When to use this
289
+
290
+ - You want to verify that a finished Devin session actually ran tests, created commits, wrote files, or pushed — not just claimed to.
291
+ - You are gating agent output in CI and need a machine-readable verdict (`PASS`/`PARTIAL`/`UNVERIFIED`) with exit codes.
292
+ - You want to audit many sessions at once, offline, without sending transcripts to an LLM — and optionally publish a single static HTML report (`devin-qa-pack report`).
293
+ - You are on a restricted machine: the tool is read-only and never touches the network.
294
+
295
+ ## When NOT to use this
296
+
297
+ - You need a review of code quality or correctness — it verifies that actions happened, not that the work is good.
298
+ - You need real-time monitoring or an MCP server (on the M2 roadmap).
299
+ - Your agent is not Devin — the ground truth comes from Devin's `sessions.db`.
300
+
301
+ ## FAQ
302
+
303
+ **How do I verify a Devin session actually ran the tests it claims?** Run `devin-qa-pack audit --session <id>`. It reads the session's `tool_call_state` rows from `sessions.db`, extracts delivery claims like "tests passed", and checks each against recorded tool calls — a claim without matching evidence resolves to `UNVERIFIED` or `PARTIAL`, not `PASS`.
304
+
305
+ **Does devin-qa-pack need network access or an API key?** No. It is a fully offline, read-only audit of the local `sessions.db`. It never calls an LLM, never sends data anywhere, and never writes to Devin's stores.
306
+
307
+ **Where does devin-qa-pack find sessions.db?** It auto-detects `%APPDATA%/devin/cli/sessions.db` on Windows, `$XDG_DATA_HOME/devin/cli/sessions.db` on Linux (`~/.local/share/devin/cli/sessions.db` by default), `~/Library/Application Support/devin/` on macOS, plus a legacy `~/.config/devin` layout. Override with `--sessions-db`.
308
+
309
+ ## License
310
+
311
+ MIT — see [LICENSE](LICENSE).
312
+
313
+
314
+ ---
315
+
316
+ If this saved you debugging time, a ⭐ on the repo helps others find it.