Skip to content

feat(reports): add plugin and agent reports beside the diff - #413

Draft
pavelzw wants to merge 4 commits into
mainfrom
feat/reports
Draft

pavelzw wants to merge 4 commits into
mainfrom
feat/reports

Conversation

@pavelzw

@pavelzw pavelzw commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Towards #269.

What

One report format, one Reports view (gr), two ways for a report to arrive.

  • Report (src/shared/protocol.ts): a title, the snapshot target it was made for (shas plus a digest of the changed blobs, so a worktree side that moved on is told apart), and blocks: markdown, rendered through the existing sandboxed renderer, or pages, old/new image pairs shown with the existing swipe, onion skin and difference comparison. A block may carry an anchor (path:line); Enter opens the diff there and c comments there, so findings become ordinary comments, in the prompt and on GitHub. Anchors the snapshot does not show are dropped with a note in the report's log.
  • Generators (crates/diffle/src/reports/): a program diffle runs when a changed file matches its globs. It gets copies of both sides (the matched files, or the whole snapshot for scope: tree) through the session's allowlisted reads, the review as JSON on stdin, and DIFFLE_OLD/DIFFLE_NEW/DIFFLE_OUT/DIFFLE_ROOT (plus DIFFLE_FILE for a per-file command). It writes report.json and its files into DIFFLE_OUT, or just prints markdown. Commands run without a shell; a | pipes one program into the next. A newer snapshot kills a run in flight, results cache by input digest, and a result commits only while its snapshot is current. Built-in rows for pixi (pixi-diff | pixi-diff-to-markdown) and typst (diffle-typst) resolve from PATH like language servers; diffle plugins lists them. Commands come from the user config only, never from the reviewed tree, so a pull request cannot bring its own.
  • Pushed reports: PUT /api/reports/{id} (files first via PUT /api/reports/{id}/files/<path>), DELETE, GET list/one/file/log. A target other than the current snapshot's answers 409 with the current one. Pushed reports persist under <git-dir>/diffle/ keyed by comment key and go stale, not away, when the diff moves. diffle report put <file> and diffle report delete <id> talk to the running server, which announces its URL in <git-dir>/diffle/server.json while it runs.
  • Client (src/client/reports/): the view with a side list, j/k over blocks, J/K over reports, status (running, failed, stale) and the log under the header.
  • example/plugins/diffle-typst: a reference generator (Python, no deps) that compiles each changed .typ on both sides to PNG pages. Manuel's inline-removals render (feat(render): typeset removed words in place ManuelLerchner/diffle#3) would slot in as that program's output.

Tests

  • crates/diffle/tests/reports.rs: push, list, persistence across servers, staleness, uploads and file serving by key, 409 on stale targets, and generators driven by test/reports/fake-generator.mjs (json and stdout modes, per-file runs, tree scope, failures, a program not on PATH, runs superseded by a refresh).
  • crates/diffle/tests/cli.rs: diffle report put end to end against a served review, and the announcement withdrawn at shutdown.
  • test/client/reports.test.ts: view state and keys.
  • test/e2e/reports.spec.ts: the generator's pages and a pushed report, then Enter and c into the diff.

Notes for review

  • The e2e snapshots under test/e2e/__snapshots__/reports.spec.ts/ were made with a local Chromium, not the Docker one; and every other spec's screenshots now show a third button in the view switch. Both need the Update snapshots workflow once CI has run.
  • Open questions from the design still stand: whether generated reports should be cached on disk across runs, and whether the catalog should learn plugins from a manifest on PATH instead of shipping rows.

Generated by Claude Code

A Reports view (gr) shows documents attached to the snapshot: generators
diffle runs when a changed file matches their globs, with copies of both
sides and the review on stdin, and reports pushed over PUT /api/reports
by an agent or `diffle report put`. Blocks are sandboxed markdown or
rendered page pairs shown with the image comparison; an anchored block
opens the diff at its line and takes a comment there. Pushed reports
persist under the git dir and go stale when the diff moves on. Built-in
rows for pixi.lock and Typst resolve from PATH; `diffle plugins` lists
them, and the config's `plugins` adds or turns one off.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY9UWfvKQAyZeDnYaZnihy
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes committed snapshots. View the snapshot report to compare them side by side.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants