diffowl 0.2.1 → 0.3.1

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.
package/README.md CHANGED
@@ -7,25 +7,29 @@
7
7
  " "
8
8
  ```
9
9
 
10
- > **Local AI Code Review Agent**
10
+ > **The verification layer for agent-written code.**
11
11
  >
12
- > Build-time quality reviews, running locally, on your own terms.
12
+ > An independent reviewer that runs locally on every commit — on the model you already use, no matter which agent (or human) wrote the code.
13
13
 
14
- DiffOwl is a lightweight CLI that integrates into your Git workflow to provide high-quality code reviews locally. Instead of rebuilding LLM integrations or managing provider keys from scratch, DiffOwl orchestrates a headless [OpenCode Server](https://opencode.ai/docs/server/) session, builds bounded local review context, and asks the local agent for structured findings.
14
+ Coding agents now write much of the code, but the agent that wrote a patch shouldn't be its only reviewer. DiffOwl is a separate, independent review pass: it builds bounded local context from your diff and asks a model for structured, durable findings. It works the same whether the change came from Claude Code, Cursor, OpenCode, or your own hands.
15
+
16
+ Under the hood it drives a headless [OpenCode](https://opencode.ai/docs/server/) session for model execution, so you bring your own provider and pay no one but them — no DiffOwl account, no service in the loop.
15
17
 
16
18
  ---
17
19
 
18
20
  ## Features
19
21
 
20
- - **Powered by OpenCode**: Integrates with OpenCode's local environment and configured providers while keeping DiffOwl's review workflow local and repeatable.
22
+ - **Agent-Agnostic**: Reviews code from any source — Claude Code, Cursor, OpenCode, or a human. The reviewer stays independent from whoever wrote the patch.
23
+ - **Provider-Neutral**: Runs on whatever model and provider you have configured in OpenCode (Copilot, OpenAI, local, and more). No separate keys, no DiffOwl account, no per-seat bill.
21
24
  - **First-Class TypeScript Support**: Automatically extracts modified TypeScript AST nodes (functions, classes, interfaces, types, enums, methods, properties, and top-level const declarations) to feed rich, structured context to the AI reviewer.
22
- - **Non-Blocking Git Hooks**: Runs post-commit reviews asynchronously in the background. It will never slow down or block your `git commit` operation.
25
+ - **Automatic Git Hooks**: Reviews run on every commit and stay out of your way results land in `.diffowl/` when they are ready.
23
26
  - **Review Chat Handoff**: Reopen the OpenCode session behind the latest or any selected review with `diffowl chat`.
24
27
  - **Review Depth Profiles**: Choose `shallow` or `default` context strategies to match fast hooks or normal reviews.
25
28
  - **Intelligent File Filtering**: Supports `include` and `exclude` glob patterns to focus reviews on source directories while skipping build artifacts, lockfiles, and node modules.
26
29
  - **Project-Specific Rules**: Inject custom guidelines directly into the reviewer's system prompt (e.g., "Check for SQL injection", "Ensure TypeScript types are explicit").
27
30
  - **Interactive Model Selector**: Automatically queries OpenCode to present a clean, interactive list of your connected providers and models.
28
- - **Local Reports**: Generates markdown reviews under `.diffowl/reviews/`, including hidden session metadata that makes reports chat-capable.
31
+ - **Local Reports**: Generates markdown reviews under `.diffowl/reviews/`, including durable finding IDs and hidden session metadata that makes reports chat-capable.
32
+ - **Durable Findings (0.3)**: Persists reviews and findings in `.diffowl/state.db` with stable `fnd_*` IDs, occurrence tracking, and lifecycle commands for fix, dismiss, defer, and reopen.
29
33
  - **Agent-Assisted Resolution**: Includes an optional portable skill that lets coding agents investigate findings, fix confirmed issues, record dismissals, and archive handled reports.
30
34
  - **Hook Log Retention**: Bounds accumulated hook logs without deleting review history.
31
35
 
@@ -35,7 +39,7 @@ DiffOwl is a lightweight CLI that integrates into your Git workflow to provide h
35
39
 
36
40
  ### 1. Prerequisites
37
41
 
38
- 1. **Verify Node.js 20 or newer is installed**:
42
+ 1. **Verify Node.js 22.14.0 or newer is installed**:
39
43
  ```bash
40
44
  node --version
41
45
  ```
@@ -137,13 +141,14 @@ The agent will:
137
141
 
138
142
  1. Treat findings as candidates and verify them against the current code.
139
143
  2. Fix confirmed issues using the repository's normal workflow.
140
- 3. Mark findings as fixed, already fixed, agent dismissed, user dismissed, deferred, or open.
141
- 4. Append a `## Resolution` checklist without rewriting the generated review.
142
- 5. Move fully handled timestamped reports into `.diffowl/reviews/resolved/`.
144
+ 3. For durable findings (0.3+), record lifecycle status with `diffowl findings fix`, `dismiss`, or `defer`.
145
+ 4. For legacy reports, mark findings as fixed, already fixed, agent dismissed, user dismissed, deferred, or open in a `## Resolution` checklist.
146
+ 5. Append or merge resolution state without rewriting the generated review body.
147
+ 6. Move fully handled timestamped reports into `.diffowl/reviews/resolved/` when every finding is complete.
143
148
 
144
- `latest.md` is only a copy of the newest report and is overwritten by future reviews. The skill updates the matching timestamped report as the durable record.
149
+ `latest.md` is only a copy of the newest report and is overwritten by future reviews. Markdown reports from 0.3+ are immutable snapshots; SQLite is the authoritative backlog for durable findings.
145
150
 
146
- The generated review content remains unchanged. Resolution state is appended under `## Resolution`. To reopen the OpenCode session for an archived report, pass its explicit path:
151
+ For legacy pre-0.3 reports, resolution state is appended under `## Resolution`. To reopen the OpenCode session for an archived report, pass its explicit path:
147
152
 
148
153
  ```bash
149
154
  diffowl chat .diffowl/reviews/resolved/review-<timestamp>.md
@@ -185,10 +190,11 @@ Runs a code review on your repository.
185
190
  - `--depth <depth>`: Overrides configured review depth. Valid values: `shallow`, `default`.
186
191
  - `--reasoning <effort>`: Overrides configured OpenCode reasoning variant. Valid values: `auto`, `none`, `minimal`, `low`, `medium`, `high`, `max`, `xhigh`.
187
192
  - `--verbose`: Includes suppressed findings and extra review details in the report.
193
+ - `--format <format>`: Output format: `text` (default) or `json`. JSON writes a versioned document to stdout and persists SQLite state.
188
194
 
189
195
  Candidates below `min_confidence` or outside changed files are excluded from actionable finding counts and review status. When any are excluded, the report includes a short diagnostic summary and points to `diffowl chat` for investigation. Outside-file candidates are shown in full with `--verbose`; below-threshold candidates remain available in the OpenCode session.
190
196
 
191
- Rendered findings have stable `Finding N` headings, making prompts such as “investigate finding 2” map directly to resolution checklist entries.
197
+ Rendered findings use stable `Finding N` headings. Reports from DiffOwl 0.3+ also include durable `fnd_*` IDs and observation classification (`new`, `existing`, `regressed`), making prompts such as “investigate finding 2” or `diffowl findings show fnd_abc` map directly to the backlog.
192
198
 
193
199
  Review depth controls both how much local context DiffOwl preloads and how much exploration the reviewer is expected to do:
194
200
 
@@ -275,6 +281,32 @@ diffowl server start
275
281
  diffowl server stop
276
282
  ```
277
283
 
284
+ ### `diffowl findings [list] | show | dismiss | defer | fix | reopen`
285
+
286
+ Inspect and manage the durable findings backlog stored in `.diffowl/state.db`.
287
+
288
+ ```bash
289
+ # List unresolved findings (open and regressed)
290
+ diffowl findings
291
+
292
+ # Inspect one finding by full id, id prefix, or latest:N
293
+ diffowl findings show fnd_abc --format json
294
+
295
+ # Mark fixed after verification
296
+ diffowl findings fix fnd_abc --note "Added null guard." --verified-by "pnpm run test"
297
+
298
+ # Dismiss a false positive
299
+ diffowl findings dismiss fnd_abc --reason "Guarded by caller."
300
+
301
+ # Defer intentionally
302
+ diffowl findings defer fnd_abc --reason "Needs upstream change."
303
+
304
+ # Reopen a previously fixed or dismissed finding
305
+ diffowl findings reopen fnd_abc --reason "Regression in new path."
306
+ ```
307
+
308
+ The unresolved backlog is durable: a finding does not auto-resolve just because a later review fails to mention it. Absence from a later model review never marks a finding fixed.
309
+
278
310
  ---
279
311
 
280
312
  ## Configuration (`.diffowl.yml`)
@@ -344,7 +376,8 @@ rules:
344
376
  Each completed review starts with a timestamped report and an ephemeral `latest.md` copy. The optional resolution skill moves fully handled timestamped reports into the resolved archive:
345
377
 
346
378
  ```text
347
- .diffowl/reviews/review-<timestamp>.md # Durable timestamped report
379
+ .diffowl/state.db # Authoritative review and finding state (0.3+)
380
+ .diffowl/reviews/review-<timestamp>.md # Immutable markdown export snapshot
348
381
  .diffowl/reviews/latest.md # Ephemeral copy of the newest report
349
382
  .diffowl/reviews/resolved/review-<timestamp>.md # Fully handled report archived by the skill
350
383
  ```
@@ -354,12 +387,31 @@ Review reports include YAML frontmatter similar to:
354
387
  ```yaml
355
388
  ---
356
389
  diffowl:
390
+ schema_version: 1
391
+ review_id: rev_...
357
392
  session_id: ses_...
358
393
  project_root: /path/to/project
359
394
  ---
360
395
  ```
361
396
 
362
- This metadata is used by `diffowl chat`. Agents may append a `## Resolution` section to timestamped reports, but should preserve the generated review body. DiffOwl does not delete review history automatically.
397
+ Finding headings in 0.3+ reports look like:
398
+
399
+ ```md
400
+ #### Finding 1 (`fnd_...`) — **new**
401
+
402
+ **[WARNING] src/auth.ts:12**
403
+ Missing null check
404
+ ```
405
+
406
+ This metadata is used by `diffowl chat`. For legacy pre-0.3 reports, agents may append a `## Resolution` section. For 0.3+ reports, use `diffowl findings *` only—do not edit markdown. DiffOwl does not delete review history automatically.
407
+
408
+ ### Upgrading to 0.3
409
+
410
+ - **No import step**: Existing markdown reports remain unchanged and chat-capable. They are not imported into SQLite.
411
+ - **New reviews persist state**: After upgrading, each `diffowl review` writes both SQLite state and a markdown snapshot.
412
+ - **Backlog semantics change**: Use `diffowl findings` for the unresolved backlog. Markdown `### Status` reflects the review snapshot only.
413
+ - **Resolution workflow**: Prefer `diffowl findings fix|dismiss|defer` over editing report checklists when durable findings exist. Never mark fixed without recorded verification (`--verified-by`).
414
+ - **Not in 0.3**: Semantic deduplication beyond fingerprint matching, automatic resolution when findings disappear, legacy report migration, retention cleanup, and SARIF export.
363
415
 
364
416
  ---
365
417