Skip to content

diffr web: search, onboarding, summaries, agent tools, and a build that fits CI - #1022

Open
milanb17 wants to merge 9 commits into
mb/diffr-web-interface-9a6716from
claude/project-thread-hwb7l0
Open

milanb17 wants to merge 9 commits into
mb/diffr-web-interface-9a6716from
claude/project-thread-hwb7l0

Conversation

@milanb17

@milanb17 milanb17 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Requested by Milan · project thread

Before: the Diffr Web job's runner was killed while it built the engine. The page had no file or text search, and summaries were not available. Hidden files took two clicks to read. Workers stayed around after the diff finished, the config box had no explanation, and three-digit line numbers ran into the splitter.

After: the engine builds in under 3 GB. ⌘P opens a file and ⌘F finds text in every diffed file. A first visit asks for a GitHub token and a summarizer key, and either one can be skipped. Summaries fold long new bodies behind pseudocode. Agents can read the comparison, save lenses, and install fold plugins through WebMCP.

This stacks on #1018.

How

  • CI memory. LLVM's wasm backend computes block reachability for every loop, and its memory grows with the square of the block count. tree-sitter-fortran's lexer needed over 11 GB even at -O0. compat.h is already included in every C file of a wasm build, so it now replaces tree-sitter's lexer macros: the generated lexer takes one step and returns, and a small driver loops. Wrapped and original lexers produced byte-identical parse trees on 9 grammars (Fortran, Julia, JS, TS, Rust, Python, C, Bash, Haskell). A full engine build peaked at 2.9 GB, against 14 GB+ before.
  • Summaries. The summarize plugin is linked natively into diffr-web (HttpHost in the plugin SDK). It reaches the model through a synchronous XHR from the worker, in a second pass after the file renders. Settings merge over config.toml as JSON overrides. When summaries fail, a dismissible notice links to settings.
  • Search. ⌘P uses VS Code's fuzzy scorer. ⌘F searches the head side whole plus the base side's removed lines, opens the folds around each match, and highlights it.
  • Agents (WebMCP). There are 11 diffr_* tools, with inputs decoded by zod/mini. That module loads only when navigator.modelContext exists. Lenses are kept per comparison: showing one folds every other file and, inside its ranges' files, every fold that holds none of those ranges. Agent plugins are JS functions that run in the workers and may change only region visibility. Settings list each plugin's code, with on/off and remove controls.
  • Smaller fixes. The tree reveals the active file only when it changes. A hidden file's root region opens with the file. Every idle worker stops after 3 s. The gutter width follows the file's longest line number.

Tested by running the page in Chromium against PRs #1017 and #1018, covering:

  • onboarding
  • tree follow
  • ⌘P and ⌘F
  • the hidden lockfile
  • idle workers (0 of 3)
  • summaries against a mocked Anthropic API, both a 200 that relabels folds and a 401 that shows the notice
  • all 11 tools, lenses, and a working, a throwing, and a non-function plugin
  • the settings reference

Also ran: cargo test -p diffr-web (7 pass), cargo xtask build-plugins, cargo fmt --check, oxfmt, oxlint, and tsc.

Note that agent plugins run like any script on the page, and that includes the worker that holds the summarizer key. The settings say to keep only plugins you trust.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp


Generated by Claude Code

claude added 4 commits October 8, 2026 06:55
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
LLVM's WebAssembly backend checks each loop for irreducible control flow
by working out which blocks reach which, in memory square in the
function's blocks. A generated lexer is one loop around a branch per
state, so tree-sitter-fortran's took over 11 GB at -O0 and the Diffr Web
job's runner was killed. The lexer now takes one step and returns where
to go next; a driver advances and calls it again. The engine build peaks
under 3 GB, and parse trees match the original lexers'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
The plugin links natively into diffr-web and reaches its model through a
synchronous request the worker makes. It runs in a second pass, so a
file shows first and its summaries follow. The page's settings merge
over config.toml as JSON overrides.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
Cmd+P goes to a file and Cmd+F finds text in every diffed file. A first
visit asks for a GitHub token and a summarizer key, both skippable, and
the settings explain diffr's configuration with a reference to every
key. WebMCP tools let an agent read the comparison, save lenses, and
install plugins that fold regions. The file tree follows the scroll, a
hidden file opens to its text, line numbers keep clear of the splitter,
and idle workers stop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
@milanb17 milanb17 self-assigned this Oct 8, 2026
claude and others added 5 commits October 8, 2026 17:12
…terTool

Chrome moved WebMCP to document.modelContext, and the current draft
dropped provideContext for registerTool, which returns a promise.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
Opening a comparison again shows each file's diff and summaries without
fetching, diffing or calling the model again. Entries are named by the
commits, the file, the engine build and its configuration; past 512 MB
the ones read longest ago go. Settings and the engine panel show the
cache's size, and Settings can clear it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
The model's answer loses the code fence models wrap it in, a docstring
opened on a line of its own is led by its first words instead of a bare
/**, and the page draws summaries upright in the editor's colour rather
than as faint italic comments.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
A browser that once held a different diffr-cache database kept the
cache off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ns4ZYciirL61M66WFtLXRp
The file tree and the diff leave out every file outside the lens, and
the summary counts only its files, as "7 of 32 files". All files lists
everything again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: 0e3ef086-d04d-46f7-a982-868add70ee04
@milanb17
milanb17 force-pushed the claude/project-thread-hwb7l0 branch from f2f27f9 to e37ee65 Compare October 8, 2026 18:43

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