paperclip/packages/paperclip-runner/docs/tutorials/local-runner.md

143 lines
5.0 KiB
Markdown

# Local runner: Run the Local Runner and Fake Harness
## What this phase is
Local runner is a local live-run path. A TypeScript mock core starts a Rust runner.
The Rust runner starts a scripted fake harness. The processes use JSON lines over
stdio.
## What this phase proves
This phase proves that a native session can run from start to finish without
Paperclip, a network provider, or a real model. It proves cleanup, request
resolution, interruption, bounded logs, one terminal result, and live/replay
parity.
## Prerequisites
- Node.js 24.11 or newer
- pnpm 9 or newer
- a stable Rust toolchain with `cargo`
- a Chromium-compatible browser
Start from a clean repository checkout and run every command from the
repository root. Install the package dependencies and browser:
```sh
pnpm install --filter @paperclipai/paperclip-runner --lockfile=false --ignore-scripts --dev
pnpm --filter @paperclipai/paperclip-runner exec playwright install chromium
```
On a minimal Linux host, install the browser libraries too:
```sh
pnpm --filter @paperclipai/paperclip-runner exec playwright install-deps chromium
```
`playwright install-deps` requires root. On a Debian or Ubuntu host where root
is unavailable, use the package's rootless verification command instead. It
downloads the required browser-library packages into a user-owned cache,
extracts them without installing system packages, and scopes `LD_LIBRARY_PATH`
to the verification process:
```sh
pnpm --filter @paperclipai/paperclip-runner verify:rootless
```
## 1. Run the package verification path
```sh
pnpm --filter @paperclipai/paperclip-runner verify
```
Expected: Rust, TypeScript, protocol, boundary, documentation, and browser
checks pass. The final Local runner line reports one terminal event and a successful
semantic result.
## 2. Run the happy path in the CLI
```sh
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario happy-path --quiet
```
Expected summary facts:
- `eventCount` is `19`;
- `terminalCount` is `1`;
- `semanticResult` is `done`;
- harness and runner exit codes are `0`.
Capture the live trace as a validated replay fixture:
```sh
# Recorded evidence generation is deferred from this release.
```
The command writes
`packages/paperclip-runner/.paperclip-local/evidence/local-runner-happy-path.json`.
## 3. Run the scripted control flows
```sh
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario permission-input --quiet
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario interrupted --quiet
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario error --quiet
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario duplicate-terminal --quiet
pnpm --filter @paperclipai/paperclip-runner trace:local-runner -- --scenario happy-path --duplicate-turn-command --quiet
```
Expected:
- permission and input finish with `done`;
- interruption exits the harness with `130` and reports `yielded`;
- scripted error exits the harness with `7` and reports `yielded`;
- duplicate terminal still reports `terminalCount: 1`;
- duplicate turn command does not start a second turn.
## 4. Use the live browser
Start the package-local server:
```sh
pnpm --filter @paperclipai/paperclip-runner browser:dev --host 127.0.0.1 --port 4179
```
Open `http://127.0.0.1:4179`, then follow these steps:
1. Keep `Happy path` selected and choose **Start local run**.
2. Confirm the terminal badge says `succeeded`.
3. Confirm `Harness process exit` is `0` and `Semantic result` is `done`.
4. Confirm `Live and replay reducer output` says `Match`.
5. Select `Permission and input`, start the run, and choose **Allow**.
6. Enter a trace name and choose **Send input**. Confirm the run completes.
Each interactive request remains open for five minutes. If it expires, the
page reports that the run finished and asks you to start a new run.
7. Select `Interruption`, start the run, and choose **Interrupt turn** when the
button becomes active.
8. Confirm the terminal badge says `cancelled`, the semantic result says
`yielded`, and the timeline contains one `run.terminal` event.
9. Switch to **Static replay** and confirm the Replay fixture path still works.
Stop Vite with `Ctrl+C`.
The browser regression suite writes its temporary screenshots under the
ignored `packages/paperclip-runner/test-results/` directory. It never rewrites
the committed protocol fixtures.
## 5. Inspect the fixtures
- [Local-runner fixtures](../../protocol/fixtures/local-runner/)
- [Local-runner protocol reference](../local-runner.md)
## What this proves
- the Rust runner owns and cleans the fake-harness process group;
- the fake driver emits deterministic live events and requests;
- logs are bounded;
- process exit and semantic result stay separate;
- duplicate commands and terminal proposals do not repeat effects;
- every browser event passes the Replay validator and reducer;
- replay after completion produces the same final snapshot.
Durable recovery must not begin until the Local runner human checkpoint is accepted.