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
20 changes: 9 additions & 11 deletions .github/workflows/rust-lite-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ on:
pull_request:
paths:
- "rust/**"
- "lite-rs/**"
- "src/**"
- "lite/**"
- "herdr-plugin.toml"
- "docs/rust-lite-parity-proof.md"
- "scripts/parity-lite.py"
- "scripts/parity-lite.sh"
- "scripts/smoke-rust-lite.sh"
- "herdr-annotate.version"
- "scripts/fetch-herdr-annotate.*"
- "scripts/lite-goldens/**"
- "scripts/lite-regression.py"
- "scripts/lite-regression.sh"
- "scripts/smoke.sh"
- "scripts/stage-local.sh"
- ".github/workflows/rust-lite-*.yml"
merge_group:

Expand Down Expand Up @@ -51,7 +52,7 @@ jobs:
workspaces: rust
- run: cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings

parity:
regression:
strategy:
fail-fast: false
matrix:
Expand All @@ -64,10 +65,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: rust
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: bash scripts/parity-lite.sh
- run: bash scripts/lite-regression.sh
2 changes: 1 addition & 1 deletion .github/workflows/rust-lite-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
run: |
version=$(sed -n 's/^version = "\(.*\)"/\1/p' rust/Cargo.toml | head -1)
test "rust-lite-v$version" = "${GITHUB_REF_NAME}"
test "$version" = "$(tr -d '[:space:]' < lite-rs/herdr-annotate.version)"
test "$version" = "$(tr -d '[:space:]' < herdr-annotate.version)"

build:
needs: verify
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/windows-full-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ on:
pull_request:
paths:
- "herdr-plugin.toml"
- "herdr-annotate.version"
- "plannotator-tui.version"
- "scripts/fetch-herdr-annotate.*"
- "scripts/fetch-plannotator-tui.*"
- "scripts/plannotator-tui.sh"
- "scripts/smoke.sh"
- "scripts/test-fetch-herdr-annotate.*"
- "scripts/test-fetch-plannotator-tui.*"
- "scripts/test-herdr-windows-plugin.ps1"
- "scripts/test-http-server.py"
Expand All @@ -33,6 +36,8 @@ jobs:
python-version: "3.11"
- name: local override and idempotence
run: ./scripts/test-fetch-plannotator-tui.ps1 -Case LocalOverride
- name: native lite local override and idempotence
run: ./scripts/test-fetch-herdr-annotate.ps1 -Case LocalOverride
- name: loopback download and checksum preservation
run: ./scripts/test-fetch-plannotator-tui.ps1 -Case Download
- uses: actions/checkout@v4
Expand All @@ -59,3 +64,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: bash scripts/test-fetch-plannotator-tui.sh
- run: bash scripts/test-fetch-herdr-annotate.sh
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
node_modules/
.DS_Store
bin/*
!bin/.gitkeep
/rust/target/
/lite-rs/bin/*
!/lite-rs/bin/.gitkeep
29 changes: 19 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ Annotate inside [Herdr](https://github.com/herdrdev/herdr): comment on any termi
## Requirements

- Herdr 0.8.0 or later
- [Bun](https://bun.sh/)
- macOS, Linux, or Windows

There is no runtime to install. Both installs download a small prebuilt `herdr-annotate` binary and verify its SHA-256 checksum.

On Linux, install `wl-clipboard`, `xclip`, or `xsel` for clipboard access.

On Windows, native Herdr plugin support is preview/best-effort. Bun must be on `PATH`. Clipboard access uses PowerShell; no extra clipboard package is required. The install, keybinding, configuration check, reload, and use instructions below also apply on Windows.
On Windows, native Herdr plugin support is preview/best-effort. Clipboard access uses PowerShell; no extra clipboard package is required. The install, keybinding, configuration check, reload, and use instructions below also apply on Windows.

## Install

Pick one. Installing the other later just swaps it (same plugin id).
Pick one. Installing the other later just swaps it (same plugin id). An install stays on the commit it came from; run the same command again to move to the current release.

<img src="assets/install-full.svg" width="200" align="left" alt="Full">

Expand Down Expand Up @@ -211,20 +212,28 @@ Herdr Annotate reads text that Herdr copies to the system clipboard. The plugin

## Development

The plugin is a Rust binary in `rust/`.

```sh
bun install
bun test
bun run typecheck
herdr plugin link "$PWD"
cargo test --manifest-path rust/Cargo.toml
cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
bash scripts/stage-local.sh # build and stage bin/herdr-annotate.exe
herdr plugin link "$PWD" # or "$PWD/lite" for the Lite variant
```

`herdr plugin link` does not run manifest build hooks, so stage the binary first. It also replaces
any existing `annotate` link; link the other directory to switch back.

`bash scripts/lite-regression.sh` checks the runtime against goldens recorded from the retired Bun
runtime. [docs/lite-testing.md](docs/lite-testing.md) covers what it compares and everything else
that guards Lite.

To test a local plannotator-tui build instead of the pinned release, put it in `bin/`
before linking: `PLANNOTATOR_TUI_BIN=/path/to/plannotator-tui bash scripts/fetch-plannotator-tui.sh`.
`herdr plugin link` replaces any existing `annotate` link; link the other directory to switch back.

Before a release, `HERDR_SESSION=<disposable session> bash scripts/smoke.sh` installs fresh, upgrades
from the first shipped commit, installs lite, swaps to full, and opens the review pane, then restores
whatever was installed.
from the first shipped commit, installs lite, swaps to full, and opens the manager and review panes,
then restores whatever was installed.

## Neovim integration

Expand Down
24 changes: 0 additions & 24 deletions bun.lock

This file was deleted.

83 changes: 83 additions & 0 deletions docs/lite-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# How Lite is tested

Herdr Annotate Lite is one native Rust binary. Its behavior was defined by the Bun runtime this
repository shipped through 0.3.0, and that definition is still enforced, by recording rather than
by running both runtimes side by side.

## Recorded goldens

`scripts/lite-regression.py` drives all six entrypoints the Lite manifest declares and compares
every observable with a recording checked in under `scripts/lite-goldens/`. The recording was taken
from the Bun runtime at commit `2add0da`, the last commit that still contained `src/`, so a green
run means the native runtime still does what Bun did.

```sh
bash scripts/lite-regression.sh
```

The wrapper builds and stages a release binary, then checks it. `rust-lite-ci` runs the same
command on Ubuntu and macOS.

### What one run compares

- Process cases: exit code, stdout, stderr, every fake `herdr` and clipboard call with its
arguments, notification arguments, clipboard bytes, pending bytes and mode, and the resulting
filesystem tree.
- Screen cases: real PTYs at 86x22 (editor) and 98x28 (manager). The ANSI model in the harness
ignores style escapes and retains the terminal cell grid, including wide-character continuation
cells. It snapshots the first frame and the frame after every input, and compares every OSC 52
clipboard sequence the pane emitted, in order. Where a case compares clipboard bytes, the last
sequence's payload must equal the bytes the native writer was handed.
- Store cases: JSONL bytes, file modes, and leftover lock and temporary files after scripted editor
and manager mutations.
- `store.cross-read`: exports `scripts/lite-goldens/fixtures/bun-editor-annotations.jsonl`, the
exact record the Bun editor wrote in the recorded run, so the on-disk format stays readable.
- Manifests: `lite/herdr-plugin.toml` and the root Full manifest must agree on the header and on
every action and pane declaration, and neither may gate the annotation tools to a platform.
- Error catalog: every user-visible message the Bun runtime produced still exists in the native
source file that owns it.
- Key coverage: the run fails unless it sent every editor and manager key in the required set.

The only normalized values are each run's temporary roots, the repository root, the per-user
handoff directory, generated UUIDs, generated ISO timestamps, and the pid and time components of
pending and temporary filenames. Seeded timestamps stay literal. Screen cells and clipboard bytes
are never normalized.

### Clipboard adapters

One clipboard operation walks the platform's candidate list until an adapter works, so the goldens
record the role (`clipboard-read`, `clipboard-write`) instead of the program and hold on every
platform. The adapters themselves, their arguments, and the fallback order are checked against
`CLIPBOARD_CANDIDATES` in the harness, which also requires a run to exercise both a first-adapter
success and the full chain. macOS therefore covers `pbpaste` and `pbcopy`, and Ubuntu covers
Wayland, then xclip, then xsel.

### Re-recording

`bash scripts/lite-regression.sh --record` rewrites the goldens from the current binary. Do that
only for a deliberate behavior change, and read the diff: every rewritten line is a behavior the
retired runtime no longer defines.

## Everything else

| Check | Command |
|---|---|
| Unit and subprocess tests | `cargo test --manifest-path rust/Cargo.toml` |
| Lints and formatting | `cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings`, `cargo fmt --manifest-path rust/Cargo.toml --check` |
| Manifest structure, including the Windows gates | `python3 scripts/test-windows-full-manifest.py` |
| Binary fetchers | `bash scripts/test-fetch-herdr-annotate.sh`, `bash scripts/test-fetch-plannotator-tui.sh`, and the `.ps1` cases in `windows-full-ci` |
| Install, upgrade, swap, and both panes in a live session | `HERDR_SESSION=<disposable session> bash scripts/smoke.sh` |

## What retiring Bun cost

The old harness ran Bun and Rust on every case in the same run, so a divergence surfaced the moment
either side moved. The comparison is now against a fixed recording: it still catches a native
regression, but it can no longer settle a *new* behavior against a live Bun reference, and a
deliberate re-record is a human decision instead of a diff against a second implementation.

`docs/rust-lite-parity.md` and `docs/rust-lite-parity-proof.md` mapped the TypeScript call paths to
the Rust ones function by function. They are retired with the runtime they describe; read them at
commit `2add0da`.

Windows stays outside the PTY harness. It is covered by the Rust tests, the manifest and fetcher
checks in `windows-full-ci`, and the manual checklist in `windows-full-acceptance.md`.
Loading
Loading