eliziff gives Beaver one address book for its legal workflows

A small internal change makes links from assistant-guided work more likely to land users in the right place.

workflowinfrastructure

eliziff has centralised the way Beaver builds links to its own screens, instead of leaving each part of the product to assemble them independently. That sounds mundane. It matters when a legal workflow moves someone from an answer or task into the document, library or review area where the work continues.

The fork also tidies the surrounding machinery: shared upload handling, fewer unused components, quieter logs, and tests aimed at visible user actions such as uploading material to the Library. It is maintenance work, but disciplined maintenance is a useful signal in a fork with 957 commits beyond the original project.

So what Teams assessing Beaver for day-to-day legal work should care because reliable handoffs between workflows and documents reduce the small friction points that derail adoption.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

22 commits from eliziff/Beaver, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
a0c9b676 chore: prune unused runtime dependencies Eli Ziff 2026-07-27 ↗ GitHub
125e2cd1 chore: keep cloud build tooling out of production installs Eli Ziff 2026-07-27 ↗ GitHub
9d316268 test: add launcher-owned production smoke Eli Ziff 2026-07-27 ↗ GitHub
770ba574 test: target visible Library upload control Eli Ziff 2026-07-27 ↗ GitHub
f2e585ba test: prove the prompt diet end to end with live calls Eli Ziff 2026-07-27 ↗ GitHub
commit body
- streamingCitationRecovery: mocked-adapter integration test that a
  truncated CITATIONS block still yields recovered citations in the
  final SSE event and never leaks into visible text.
- prompt-live-harness: six new adversarial scenarios (no page markers,
  multi-doc attribution, mixed pdf+spreadsheet, fabrication trap,
  page-break quoting, prompt injection). 57/60 across three OpenAI
  tiers; injection and multi-doc 6/6 each. Old-arm scaffolding removed
  now the pre/post-trim comparison is archived in benchmarks.
- prompt-cache-check: provider counters prove the conditional
  spreadsheet splice reuses the identical 2,304 cached prefix tokens.
- liveToolLoop: real-model E2E through the account-free /chat route;
  the model reads an uploaded lease via library tools and routes a
  drafting-errors request to library_lint_docx_structure, relaying its
  verified findings. Gated behind LIVE_E2E=1.
- citations: extract shared extractJsonObjects so the truncation
  scanner exists once, used by both the server and the harness.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
557f6088 test: reusable browser gate for legal deep links Eli Ziff 2026-07-27 ↗ GitHub
commit body
Playwright/Chromium suite that opens real pinpoint URLs against live
court sites and asserts what server probes cannot see: anchor exists
and the viewport landed on it, the page still scrolls afterwards (the
site_preference=mobile regression detector), and expected text renders.
Fresh context per case so Decisia's SITE_PREFERENCE cookie cannot leak
between cases. Includes a negative control (the bare Decisia shell URL
must fail) and a no-anchor bench judgment documenting graceful
degradation. 6/6 on SCC/ONCA/NSCA samples, screenshots archived under
benchmarks/deeplink_gate/. Accepts the SourceDoc gate-urls.json shape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
d947dc6d chore: trim dead API surface, hot-path log garbage, test flake Eli Ziff 2026-07-27 ↗ GitHub
commit body
knip sweep (script entry points and stage-3 surfaces excluded): 12
internal-only types lose their export, the mcpConnectors barrel drops
five type re-exports and validateRemoteMcpUrl nobody imported, and
llm/index's streamCodex wrapper goes private. contextBuilders no
longer materializes the whole doc index into fresh objects on every
chat turn for a dev-only log line. providerPdfLibraryBridge's backoff
test stops racing its detached background write under full-suite load
(waitFor 1s default -> bounded 10s).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
19178325 refactor: one abort helper for all LLM adapters Eli Ziff 2026-07-27 ↗ GitHub
commit body
Five adapters each carried identical abortError/throwIfAborted
copies; codex additionally exported its own name for the app-server
adapter. All six files now share llm/abort.ts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
1050ff3f refactor: drop three unreachable inline-markup patterns Eli Ziff 2026-07-27 ↗ GitHub
commit body
nextInlineMatch listed <strong|b>, <em|i> and <code> twice. The earlier
entries match everywhere the later ones do and win the priority tie, so the
duplicates were dead weight executed against every offset of every legal
document rendered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
8d58d873 fix: find soffice.exe on Windows; drop dead exports and spent probes Eli Ziff 2026-07-27 ↗ GitHub
commit body
resolveSofficeBinaryPaths probed only extensionless soffice plus Unix
install paths, so DOCX->PDF reported LibreOffice missing on every
Windows machine even with soffice.exe installed and on PATH. Probe
.exe names and the Program Files install dirs on win32. Verified with
a real conversion: hello.docx -> 19,351-byte %PDF in 2.2s.

Also: unexport four knip-flagged dead surfaces (the projects.ts
handleDocumentUpload twin of the documents.ts one is now internal;
dedup of the two bodies queued), drop the supabase.ts legacy re-export
of isServerSupabaseConfigured, and delete three spent probe scripts
whose results are recorded in commit messages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
fb4d47c1 refactor: collapse repeated blocks in documents routes and documentOps Eli Ziff 2026-07-27 ↗ GitHub
commit body
routes/documents.ts carried the same select-doc/ensureDocAccess/404
block ten times, the extension allowlist three times, the best-effort
Office->PDF rendition four times, and the version-insert/point-current
pair twice; each is now one helper with identical status codes, check
ordering, and response bodies. documentOps' generateDocx duplicated
persistGeneratedFile end to end - it now delegates (generated DOCX
still gets no PDF rendition), and read_document's dev-log narration
went with it. -420 lines across the pair.

Verified: tsc clean, 8 affected suites (53 tests) green, filenames and
result shapes byte-compatible (renderer already used
safeGeneratedFilename, persistGeneratedFile returns the legacy shape).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
103b8b3d refactor: one handleDocumentUpload for projects, documents, library Eli Ziff 2026-07-27 ↗ GitHub
commit body
routes/projects.ts carried a 140-line near-verbatim twin of the
documents.ts upload handler. The documents.ts version is a superset:
library_kind defaults to 'file' in both (explicit vs column default)
and the only response delta is an additive folder_id: null. Projects
now imports the shared handler; four upload-only imports pruned.

Verified: tsc clean; projects.routes suite green. The
localMatter.routes failure in the same run predates this change - it
expects the old attached-document message format while another
session's uncommitted contextBuilders.ts WIP emits the new one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
11b22f40 feat: canonical in-app route builder (appRoutes) Eli Ziff 2026-07-27 ↗ GitHub
Single source for Beaver app URLs so tools emit app_url values instead
of hand-built route strings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
1e62c26e feat: workflow tools with app_url surfacing; assistant tool compaction Eli Ziff 2026-07-27 ↗ GitHub
commit body
list_workflows/read_workflow join the local assistant toolset, tools
return canonical app_url values via appRoutes, and the workflows route
gains local coverage. localAssistantTools also lands its compaction:
a tool() schema builder over all hand-written schemas, shared arg
coercion helpers, one DOCX_WORKFLOWS dispatch table for the three
structurally identical library workflows, and fail()/errorText()
replacing ~30 identical error wraps (tool names, schemas, and result
JSON key order unchanged).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUsMXzBsEJ27DjJVPSfW5o
2512207f test: prune tautological and duplicated backend assertions Eli Ziff 2026-07-27 ↗ GitHub
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yXxuitxX5h4wm1v88hnga
db5e6f50 test: cut backend suites down to useful coverage; matrix entries for new fixtures Eli Ziff 2026-07-27 ↗ GitHub
commit body
Consolidates downloadTokens, llmModels, safeError, and storage suites to the
assertions that catch real regressions; sourceDocFixtures matrix now derives
its inventory from the fixture directory and covers the seven limitation and
honest-performance fixtures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yXxuitxX5h4wm1v88hnga
96c629bb test: await lazy document renderer Eli Ziff 2026-07-28 ↗ GitHub
4659ac9c Servers own tokens, models own choices: three courier jobs removed Eli Ziff 2026-07-29 ↗ GitHub
commit body
version_id leaves the revise contract (server resolves the active
version; providing one still asserts). Native notes leave the drafting
extraction as [^id] markers with definitions, so precedent adaptation
carries tokens instead of converting notation; multi-paragraph bodies
flatten deterministically with a typed warning. The tool-round budget
sentence duplicated harness enforcement and is gone. Corpus paths follow
the benchmarks/ vendoring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
d90201fa Absorb in-flight backend work from the parallel session Eli Ziff 2026-07-29 ↗ GitHub
commit body
Inherited working-tree state now owned by this line of work: store and
route changes, tool dispatcher and streaming updates, test adjustments,
and the attachment announced-not-preloaded contract (the session note
accompanying it is honored and removed). Also carries this session's
prompt-variant conditionals and shape-aware prompt text in routes/chat.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
e94e242d Absorb in-flight frontend surface work from the parallel session Eli Ziff 2026-07-29 ↗ GitHub
commit body
Account, library, projects, tabular, and workflow surfaces plus shared
components and hooks, inherited as working state and owned from here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
622b01ae checkpoint: integrate assistant reliability and legal sources Eli Ziff 2026-07-30 ↗ GitHub
2d71dccc dedupe sha256 onto shared hash helper Eli Ziff 2026-08-02 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-840.md from inside the repo you want the changes in.

⬇ Download capture-thread-840.md