143 lines
5.0 KiB
Markdown
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.
|