Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ All notable changes to vouch are documented here. Format follows

## [Unreleased]

### Docs
- example KBs now carry their own screenshots: `examples/README.md` and the
`tiny/` + `decision-log/` READMEs embed terminal renders of `vouch status`,
`search`, `show`, `audit`, and a supersession `diff` against the shipped
fixtures, so a reader can see what vouch looks like before installing it.
Images live under `docs/img/examples/` and are generated deterministically
from the fixtures by `docs/img/examples/render.py` (`make
examples-screenshots`); `tests/test_example_screenshots.py` asserts the
committed SVGs stay reproducible (#286).

### Added
- `vouch dual-solve <issue-url>` — run claude + codex on one github issue in
isolated git worktrees, compare the two diffs, keep the branch you pick, and
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help install dev test test-cov lint format type check build clean
.PHONY: help install dev test test-cov lint format type check build clean examples-screenshots

PY ?= python
PIP ?= $(PY) -m pip
Expand All @@ -15,6 +15,7 @@ help:
@echo " make check lint + type + test"
@echo " make build build sdist + wheel"
@echo " make clean remove caches, build artifacts, *.egg-info"
@echo " make examples-screenshots re-render docs/img/examples/*.svg"

install:
$(PIP) install -e '.[dev]'
Expand All @@ -38,6 +39,9 @@ type:

check: lint type test

examples-screenshots:
$(PY) docs/img/examples/render.py

build:
$(PY) -m pip install --upgrade build
$(PY) -m build
Expand Down
24 changes: 24 additions & 0 deletions desktop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# deps
node_modules/
src/renderer/node_modules/

# build output
dist/
out/
release/
*.log
*.tsbuildinfo

# os
.DS_Store
Thumbs.db

# editor / local
.vscode/
.idea/
.claude/
.superpowers/
docs/superpowers/
docs/releases/
*.local
.env
64 changes: 64 additions & 0 deletions desktop/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Changelog

All notable changes to vouch-desktop are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [1.0.0] — 2026-06-26

### Changed
- **Reshaped to React + TypeScript + electron-vite.** The renderer is rebuilt as
React 18 components (`src/renderer/src/`); main and preload are converted from
plain JS to TypeScript. electron-vite replaces the buildless setup, producing
three typed targets (main → CJS, preload → CJS, renderer → React/ESM).
- **Typed IPC contract.** `src/shared/ipc.ts` declares the `VouchApi` interface
and all channel payload/return types; main, preload, and renderer share it as a
single source of truth. No behavior change — same channels, same semantics.
- **Generated typed catalog.** `scripts/gen-methods.ts` now emits
`src/shared/methods.gen.ts` (a typed `Method[]` array + a `MethodName` union)
instead of a plain JSON file. The generator's `enrich()` function is unit-tested.
- All 11 views, the dark theme, the form generator, result renderers, review gate,
and dual-solve runner are faithful ports — **behavior unchanged**.
- Tests migrated to Vitest; 85 tests covering catalog, gen-methods, vouch-locator,
http-client, jsonl-client, MethodForm collect parity, controls, and MethodCard.

## [0.1.0] — 2026-06-26

### Added
- Initial Electron desktop app: a GUI over the full vouch `kb.*` command surface
(all 54 methods), plus a bespoke dual-solve runner.
- **Process bridge.** Main-process `JsonlClient` spawns `vouch serve --transport
jsonl` and exchanges newline-delimited JSON, correlating responses by `id`,
with per-method timeouts (long ops get 10 min). A `Supervisor` health-polls
`kb.status`, restarts the child with backoff, and surfaces process state.
- **Lazy dual-solve.** An `HttpClient` spawns
`vouch review-ui --allow-dual-solve --dual-solve-sandbox` only when the
Dual-Solve view is opened, drives `/dual-solve/run|job|choose`, and streams
phase progress over the review-ui `/ws`. The review queue itself runs over
JSONL, so the rest of the app needs no `[web]` extra.
- **Data-driven forms.** A single form generator builds typed controls from a
verified parameter catalog (`scripts/gen-methods.ts` → `src/shared/methods.gen.ts`):
text/textarea, number/slider, toggle, tag input, JSON editor, enum select and
combobox (option lists taken from vouch's own model enums), native file/save
pickers, and a search-backed id typeahead for reference params.
- **Views.** Dashboard, Search & Ask, Browse, Propose, Review & Lifecycle (with a
pending-queue + approve/reject), Sessions, Graph, Maintenance, Export/Import,
Audit, and Dual-Solve. A detail drawer opens any claim/page/entity/relation.
- **Capability-gating.** Methods not advertised by the connected vouch are shown
disabled; views light up automatically when vouch is upgraded.
- **Companion.** Tray icon with pending-count badge + KB switcher, native OS
notifications (dual-solve ready, new pending proposals, process down), and a
no-terminal launch flow (open/init a KB, the app supervises vouch).
- **Review gate preserved.** The UI never auto-approves; durable writes only ever
happen through vouch's own `propose → approve` flow.
- Sandboxed renderer (`contextIsolation`, `sandbox`, no node), a single frozen
`window.vouch` preload bridge, and a tight Content-Security-Policy.
- electron-builder config for dmg / nsis / AppImage; a layered vouch locator
(configured path → bundled-frozen → PATH → `python -m vouch`).
- Tests: a catalog-coverage suite (`npm test`) and a JSONL smoke harness against
a real vouch binary (`npm run smoke <kbRoot>`).

### Not yet covered
- The CLI-only orchestration commands `auto-pr`, `migrate`, `schema`, and
`sync-check`/`sync-apply` are not yet surfaced in the UI.
- Packaging a bundled, frozen vouch (PyInstaller) for zero-Python installs is
scaffolded (`scripts/freeze-vouch.sh` slot, `extraResources`) but not built.
21 changes: 21 additions & 0 deletions desktop/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 vouch-desktop contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
144 changes: 144 additions & 0 deletions desktop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# vouch-desktop

A cross-platform **Electron** desktop app that puts a GUI on the entire
[vouch](https://github.com/vouchdev/vouch) command surface — the review-gated,
local-first decision-memory knowledge base.

![The vouch-desktop dashboard — health, artifact counts, and review throughput for the open knowledge base](docs/screenshots/dashboard.png)

vouch is an **unmodified dependency**: vouch-desktop spawns the `vouch` CLI's
machine transports and never patches its Python source. It talks to vouch two
ways, and never writes durable KB state except through vouch's own
**propose → approve** review gate.

- **JSONL stdio** (`vouch serve --transport jsonl`) — the workhorse. All 54
`kb.*` methods (read, search, list, propose, review, lifecycle, sessions,
graph, maintenance, export/import, audit) flow over one newline-delimited
JSON pipe.
- **HTTP + WebSocket** (`vouch review-ui --allow-dual-solve`) — spawned lazily,
only when you open the Dual-Solve view, for the one thing JSONL can't do:
the long-running, sandboxed two-engine dual-solve runner with streamed
progress.

## What you get

- **One window over every command.** A left-rail of ten task-shaped views plus a
bespoke Dual-Solve runner. Data-entry methods get forms **generated** from a
verified parameter catalog (typed controls, enum dropdowns, sliders, tag
inputs, native file pickers, and search-backed id typeaheads) — so the UI
stays in step with vouch instead of hand-coding 54 forms.
- **The gate, made visible.** Propose anything; it lands in the review queue.
Approve / reject from the Review view. Nothing is ever auto-approved.
- **Capability-aware.** Methods the connected vouch doesn't advertise are shown
disabled, and light up automatically when you upgrade vouch.
- **A companion, not just a window.** Tray icon with a pending-count badge and KB
switcher, native notifications (a dual-solve run is ready to judge; new
proposals arrived; the process went down), and no terminal required — the app
finds, launches, and supervises vouch for you.

## A look around

| The gate, made visible | Forms from the catalog |
|---|---|
| [![Review & Lifecycle — the pending queue with approve/reject controls](docs/screenshots/review.png)](docs/screenshots/review.png) | [![Browse — read methods rendered as generated forms](docs/screenshots/browse.png)](docs/screenshots/browse.png) |
| Propose anything and it lands in the **review queue**. Approve or reject it here — nothing is ever auto-approved. | Every method gets a typed form **generated** from the verified parameter catalog, with id typeaheads and result cards. |

The bespoke **Dual-Solve** runner is the one thing JSONL can't do — it drives
vouch's sandboxed two-engine runner over HTTP, streams progress, then proposes
the winning diff into the same review queue:

[![Dual-Solve — run claude and codex on one issue, compare diffs, pick a winner](docs/screenshots/dual-solve.png)](docs/screenshots/dual-solve.png)

## Requirements

- **Node 18+** and **npm** to build/run from source (Node 20+ recommended).
- **vouch** on your `PATH` (`pipx install vouch`), or set its path in the app.
Dual-solve additionally needs vouch's `[web]` extra (`pipx install
'vouch[web]'`), `git` / `gh` / `docker` on `PATH`, the `vouch/coder:latest`
sandbox image, and the KB inside a git repository.

## Quick start

From the monorepo root, enter the desktop package first:

```bash
cd desktop
npm install
npm start
```

On first launch, **Open existing…** a folder containing a `.vouch/` directory,
or **Initialize new…** to create one. The app spawns and supervises the vouch
process; you never touch a shell.

## Tech stack

React 18 + TypeScript 5 renderer, built with **electron-vite** (three-target
build: main → CJS, preload → CJS, renderer → React/ESM). Vitest 2 +
`@testing-library/react` for unit tests. Typed IPC contract shared between main,
preload, and renderer via `src/shared/ipc.ts`; typed parameter catalog in
`src/shared/methods.gen.ts` (generated from `src/catalog/methods.json`).

## Develop

```bash
npm run dev # electron-vite dev — launches Electron with HMR
npm run dev:vouch # dev mode pinned to ../.venv/bin/vouch; restarts on Python changes
npm run build # electron-vite build → out/main, out/preload, out/renderer
npm test # vitest run — catalog, gen-methods, form, controls (85 tests)
npm run typecheck # tsc -b --noEmit across main + preload + renderer
npm run gen:methods # regenerate src/shared/methods.gen.ts from src/catalog/methods.json
npm run dist # electron-vite build + electron-builder → dmg / nsis / AppImage
```

From the monorepo root, the same validation gate is available as
`make desktop-check`.

For Python + desktop development from the monorepo root, use the universal
dev-loop command:

```bash
make desktop-dev-vouch KB=/path/to/repo-with-.vouch
```

It runs `electron-vite dev`, refreshes the editable vouch install when needed,
sets `VOUCH_DESKTOP_VOUCH_PATH` to the root `.venv/bin/vouch`, opens the
optional `KB=` path, and restarts Electron whenever vouch's Python sources or
schema/template files change. Once a KB is open, the desktop app starts vouch as
`.venv/bin/vouch serve --transport jsonl`, so the next restart picks up Python
code changes cleanly.

`src/catalog/methods.json` is the verified surface catalog (method names,
parameters, types, enum sets) extracted from vouch's source. `scripts/gen-methods.ts`
enriches it and writes `src/shared/methods.gen.ts`, which drives the form
generator. Regenerate it when vouch's surface changes.

To ship a zero-Python install, freeze vouch with PyInstaller into
`resources/vouch/` (see `scripts/freeze-vouch.sh`); the locator prefers it.

## Architecture

```
renderer (sandboxed, no node)
│ window.vouch.call(method, params) ← one frozen preload bridge
▼ IPC
main process
├─ JsonlClient → vouch serve --transport jsonl (all 54 kb.* methods)
├─ HttpClient → vouch review-ui --allow-dual-solve --dual-solve-sandbox
├─ Supervisor → health poll, restart, shutdown
├─ Tray/Notifier → companion + OS notifications
└─ KbStore → recent KBs, prefs
```

See [`docs/architecture.md`](./docs/architecture.md) for the full design,
including the method-by-method coverage table.

## Status

v0.1.0 covers the entire `kb.*` surface plus dual-solve. The CLI-only
orchestration commands (`auto-pr`, `migrate`, `schema`, `sync-*`) are not yet
surfaced — see the [CHANGELOG](./CHANGELOG.md).

## License

MIT.
Loading
Loading