mechbench 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mechbench-0.5.0/PKG-INFO +214 -0
- mechbench-0.5.0/README.md +183 -0
- mechbench-0.5.0/mechbench/__init__.py +13 -0
- mechbench-0.5.0/mechbench/cli.py +334 -0
- mechbench-0.5.0/mechbench.egg-info/PKG-INFO +214 -0
- mechbench-0.5.0/mechbench.egg-info/SOURCES.txt +44 -0
- mechbench-0.5.0/mechbench.egg-info/dependency_links.txt +1 -0
- mechbench-0.5.0/mechbench.egg-info/entry_points.txt +2 -0
- mechbench-0.5.0/mechbench.egg-info/requires.txt +11 -0
- mechbench-0.5.0/mechbench.egg-info/top_level.txt +2 -0
- mechbench-0.5.0/mechbench_runner/__init__.py +12 -0
- mechbench-0.5.0/mechbench_runner/_smoke.py +72 -0
- mechbench-0.5.0/mechbench_runner/api_client.py +247 -0
- mechbench-0.5.0/mechbench_runner/channel.py +405 -0
- mechbench-0.5.0/mechbench_runner/config.py +102 -0
- mechbench-0.5.0/mechbench_runner/control.py +543 -0
- mechbench-0.5.0/mechbench_runner/credentials.py +157 -0
- mechbench-0.5.0/mechbench_runner/doctor.py +317 -0
- mechbench-0.5.0/mechbench_runner/exits.py +32 -0
- mechbench-0.5.0/mechbench_runner/install.py +217 -0
- mechbench-0.5.0/mechbench_runner/job_runner.py +437 -0
- mechbench-0.5.0/mechbench_runner/login.py +402 -0
- mechbench-0.5.0/mechbench_runner/logs.py +182 -0
- mechbench-0.5.0/mechbench_runner/machine.py +48 -0
- mechbench-0.5.0/mechbench_runner/mcp_server.py +120 -0
- mechbench-0.5.0/mechbench_runner/models_cmd.py +82 -0
- mechbench-0.5.0/mechbench_runner/paths.py +28 -0
- mechbench-0.5.0/mechbench_runner/service.py +304 -0
- mechbench-0.5.0/mechbench_runner/supervisor.py +252 -0
- mechbench-0.5.0/mechbench_runner/updater.py +244 -0
- mechbench-0.5.0/mechbench_runner/watchdog.py +107 -0
- mechbench-0.5.0/pyproject.toml +76 -0
- mechbench-0.5.0/setup.cfg +4 -0
- mechbench-0.5.0/tests/test_channel.py +248 -0
- mechbench-0.5.0/tests/test_control.py +182 -0
- mechbench-0.5.0/tests/test_credentials.py +173 -0
- mechbench-0.5.0/tests/test_doctor.py +240 -0
- mechbench-0.5.0/tests/test_install.py +144 -0
- mechbench-0.5.0/tests/test_logs.py +36 -0
- mechbench-0.5.0/tests/test_pipeline_jobs.py +45 -0
- mechbench-0.5.0/tests/test_promotion.py +116 -0
- mechbench-0.5.0/tests/test_service.py +193 -0
- mechbench-0.5.0/tests/test_signed_out.py +116 -0
- mechbench-0.5.0/tests/test_supervision.py +142 -0
- mechbench-0.5.0/tests/test_supervisor.py +137 -0
- mechbench-0.5.0/tests/test_updater.py +171 -0
mechbench-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mechbench
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: The mechbench runner: claims jobs from mechbench-api, executes protocols against mechbench-compute, and emits results. Also exposes those primitives as MCP tools.
|
|
5
|
+
Author-email: Benji Smith <benji@shaxpir.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mechbench/mechbench-runner
|
|
8
|
+
Project-URL: Website, https://mechbench.ai
|
|
9
|
+
Keywords: interpretability,mechanistic-interpretability,mlx,mcp,runner
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: <3.15,>=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: mcp<2,>=1.2
|
|
22
|
+
Requires-Dist: mechbench-compute>=0.11
|
|
23
|
+
Requires-Dist: mechbench-schema>=0.13
|
|
24
|
+
Requires-Dist: certifi>=2024.2
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Requires-Dist: websockets>=13
|
|
27
|
+
Requires-Dist: pydantic>=2.7
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
31
|
+
|
|
32
|
+
# mechbench (the runner)
|
|
33
|
+
|
|
34
|
+
The `mechbench` command: what you install on a machine to connect it to
|
|
35
|
+
[mechbench.ai](https://mechbench.ai). The repository keeps its old name
|
|
36
|
+
— the PyPI package and the command are `mechbench` (task 000307), and
|
|
37
|
+
the distribution ships two modules: `mechbench`, the bare front door,
|
|
38
|
+
and `mechbench_runner`, the engine it dispatches into.
|
|
39
|
+
|
|
40
|
+
The machine-side process of the [mechbench](https://mechbench.ai) family: it claims queued jobs from `mechbench-api`, executes them against `mechbench-compute`, and posts results back. It also exposes those same primitives as [Model Context Protocol](https://modelcontextprotocol.io) tools, so an LLM agent can call them directly.
|
|
41
|
+
|
|
42
|
+
**Status:** in use. `login` pairs a machine with an account; the runner then claims and executes jobs, reports progress and preparing steps, holds a live WSS channel for control and telemetry, and installs as a launchd or systemd service so it survives reboots. `doctor` tells you whether a machine will work before it tries. Three MCP tools (`run_protocol`, `get_result`, `list_jobs`) expose the same primitives to an agent.
|
|
43
|
+
|
|
44
|
+
## What this repo is for
|
|
45
|
+
|
|
46
|
+
Two adjacent surfaces for different callers:
|
|
47
|
+
|
|
48
|
+
1. **MCP server.** An LLM agent (Claude, others) connects via MCP stdio and calls mechbench primitives as structured tools. Tool bodies run in-process against `mechbench-compute`.
|
|
49
|
+
2. **Job-runner.** Polls `mechbench-api`'s `/jobs/next` for UI-queued protocols, runs them, posts results back. Same compute path as the MCP `run_protocol` tool; different *trigger*.
|
|
50
|
+
|
|
51
|
+
Both modes share one binary (`mechbench`) with subcommands; they share the loaded model, API client, and protocol executor. Splitting into separate processes is a later operational decision — see "Open design questions" below.
|
|
52
|
+
|
|
53
|
+
## Architectural decisions (task 000185)
|
|
54
|
+
|
|
55
|
+
- **Python.** `mechbench-compute` is Python; delegating to Python via RPC or subprocess-shell from a TS runner adds a layer that pays no dividends in v0. The MCP Python SDK is mature.
|
|
56
|
+
- **One binary, two subcommands.** `mechbench mcp` launches the MCP server over stdio; `mechbench run` starts the job-runner loop. They share `ExperimentRunner` (owns the loaded Gemma model) and `ApiClient`.
|
|
57
|
+
- **Agent authenticates to `mechbench-api` with a dedicated API key**, not a user's personal session. Export `MECHBENCH_API_KEY` (mint one at `/settings/api-keys`, or via `POST /auth/api-keys`). Matches the pattern from the e2e trace.
|
|
58
|
+
- **MCP `run_protocol` runs in-process**, not queued through `mechbench-api`. The MCP caller wants the answer; we are the compute target. Job-queue round-tripping exists for the *UI-triggered* path (job-runner subcommand).
|
|
59
|
+
- **stdio transport only.** SSE / HTTP-SSE transports earn their seat once remote MCP deploy matters (deferred).
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv tool install --managed-python mechbench
|
|
65
|
+
mechbench login
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`--managed-python` has uv fetch its own interpreter rather than adopt
|
|
69
|
+
whichever `python3` the machine happens to have. It costs a one-time
|
|
70
|
+
download and buys a version we support (3.11–3.14) on a machine whose
|
|
71
|
+
own Python we then never touch. `pipx install mechbench` works
|
|
72
|
+
too, against an interpreter you already have.
|
|
73
|
+
|
|
74
|
+
`login` prints a link and waits. Open it, approve the machine — the page
|
|
75
|
+
names it, along with its host and platform, before you do — and the
|
|
76
|
+
runner collects a credential it writes to `~/.mechbench/config.toml`
|
|
77
|
+
(mode 0600). Nothing durable passes through your hands: the code in the
|
|
78
|
+
URL grants nothing on its own, and the key is minted directly to the
|
|
79
|
+
machine that asked.
|
|
80
|
+
|
|
81
|
+
For a machine with no browser, `mechbench login --token mbr_…`
|
|
82
|
+
takes a single-use token minted at [mechbench.ai/download](https://mechbench.ai/download).
|
|
83
|
+
|
|
84
|
+
`login` then offers to start the runner automatically. Say yes and there
|
|
85
|
+
is nothing further to do: it starts at login, comes back after a crash,
|
|
86
|
+
and is controlled from the website.
|
|
87
|
+
|
|
88
|
+
### Updating
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mechbench update
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Upgrades and restarts the service. **Re-running the install command does
|
|
95
|
+
not upgrade anything** — `uv tool install` treats an already-installed
|
|
96
|
+
tool as nothing to do and reports that in a way that reads like success,
|
|
97
|
+
so a machine can sit on an old version while looking freshly installed.
|
|
98
|
+
`update` verifies by reading the installed version back afterwards
|
|
99
|
+
rather than trusting an exit code, and rolls back if the new version
|
|
100
|
+
cannot start.
|
|
101
|
+
|
|
102
|
+
`mechbench doctor` answers "will this actually work here" —
|
|
103
|
+
Python, backend, credentials, API, model cache, disk — before you find
|
|
104
|
+
out the slow way.
|
|
105
|
+
|
|
106
|
+
Running a model needs Apple Silicon (the MLX backend from
|
|
107
|
+
`mechbench-compute`). The rest installs anywhere.
|
|
108
|
+
|
|
109
|
+
### Running it yourself
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
mechbench run # foreground, ^C to stop
|
|
113
|
+
mechbench install-service # or have the OS keep it running
|
|
114
|
+
mechbench service-status
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The service is supervised by launchd or systemd rather than by anything
|
|
118
|
+
we wrote — see `mechbench_runner/exits.py` for the contract that makes
|
|
119
|
+
that work.
|
|
120
|
+
|
|
121
|
+
**On macOS you will be told that software from "Ned Deily" can run in
|
|
122
|
+
the background.** That is this runner. macOS attributes a background
|
|
123
|
+
item to whoever code-signed the executable, and the executable is the
|
|
124
|
+
Python interpreter, which Ned Deily signs as CPython's macOS release
|
|
125
|
+
manager. Turning it off in Login Items & Extensions stops the runner;
|
|
126
|
+
`mechbench doctor` reports it if that happens.
|
|
127
|
+
|
|
128
|
+
### From a checkout
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git clone https://github.com/mechbench/mechbench-runner.git
|
|
132
|
+
cd mechbench
|
|
133
|
+
python3.11 -m venv .venv
|
|
134
|
+
source .venv/bin/activate
|
|
135
|
+
pip install -e '.[dev]'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Usage
|
|
139
|
+
|
|
140
|
+
### MCP server
|
|
141
|
+
|
|
142
|
+
Launch as a stdio MCP server — connect from Claude Desktop via `claude_desktop_config.json`:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"mechbench": {
|
|
148
|
+
"command": "/abs/path/to/mechbench/.venv/bin/mechbench",
|
|
149
|
+
"args": ["mcp"],
|
|
150
|
+
"env": {
|
|
151
|
+
"MECHBENCH_API_URL": "http://localhost:3000",
|
|
152
|
+
"MECHBENCH_API_KEY": "mbk_..."
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Three tools appear in Claude:
|
|
160
|
+
|
|
161
|
+
| tool | description |
|
|
162
|
+
|---|---|
|
|
163
|
+
| `run_protocol` | Run a layer-ablation protocol in-process on a prompt; return per-layer damage. |
|
|
164
|
+
| `get_result` | Fetch a cached payload from `mechbench-api` by MechbenchPath. |
|
|
165
|
+
| `list_jobs` | List the caller's queued / running / completed jobs. |
|
|
166
|
+
|
|
167
|
+
### Job-runner
|
|
168
|
+
|
|
169
|
+
Polls `mechbench-api` for UI-queued jobs. Same compute path as `run_protocol`; different trigger.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
export MECHBENCH_API_URL=http://localhost:3000
|
|
173
|
+
export MECHBENCH_API_KEY=mbk_...
|
|
174
|
+
mechbench run
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Ctrl-C exits cleanly. API-unreachable is retried with exponential backoff capped at 30 s.
|
|
178
|
+
|
|
179
|
+
### In-process smoke test
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
mechbench smoke # quick: list_jobs + get_result
|
|
183
|
+
mechbench smoke --full # adds run_protocol (42 forwards, ~1-2 min)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Configuration
|
|
187
|
+
|
|
188
|
+
All via env vars:
|
|
189
|
+
|
|
190
|
+
| var | default | purpose |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| `MECHBENCH_API_URL` | `https://api.mechbench.ai` | mechbench-api base URL. Set it to `http://localhost:3000` to develop against a local API. Ignored when credentials are stored, which carry their own. |
|
|
193
|
+
| `MECHBENCH_API_KEY` | *(from `login`)* | Overrides the stored credential entirely, URL included. For CI and containers, which have nowhere to put a config file. |
|
|
194
|
+
| `MECHBENCH_POLL_INTERVAL_SECONDS` | `2.0` | Job-runner poll cadence. |
|
|
195
|
+
| `MECHBENCH_WARM_MODEL_ID` | *(none)* | Optional model to load at startup so the first job skips cold start. There is deliberately no default: a protocol names the model it runs against, and a job that names none is an error. |
|
|
196
|
+
| `MECHBENCH_WATCHDOG_SECONDS` | `900` | How long without progress counts as wedged. `0` disables it. |
|
|
197
|
+
|
|
198
|
+
## Relationship to other mechbench repos
|
|
199
|
+
|
|
200
|
+
- **`mechbench-compute`** — imported directly. `Model`, `Ablate`, hook-aware forward.
|
|
201
|
+
- **`mechbench-schema`** — produces `LayerAblationPayload` etc. as typed results.
|
|
202
|
+
- **`mechbench-api`** — the runner's only platform dependency. All workspace state (jobs, cache reads) goes through it.
|
|
203
|
+
- **`mechbench-ui`** — no coupling. UI queues jobs; the job-runner consumes them.
|
|
204
|
+
- **`mechbench-experiments`** — research scripts that use `mechbench-compute` directly, without the job machinery.
|
|
205
|
+
|
|
206
|
+
## Open design questions (deferred)
|
|
207
|
+
|
|
208
|
+
- **One binary or two processes?** Current answer: one binary, two subcommands. Revisit if MCP-caller frequency vs. job-runner throughput diverges enough to want independent scaling.
|
|
209
|
+
- **Structured-summary interface.** The family's philosophy doc describes a read-side surface where agents consume JSON summaries of findings / experiments. Currently implicit in `list_jobs` + `get_result`. A richer summary layer (`GET /summary`, `POST /query`) is still on the table but unbuilt.
|
|
210
|
+
- **MCP-surface observability.** Rate limits, per-tool metrics, audit trail for the tool-calling side. Deferred until a second LLM-agent consumer exists.
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# mechbench (the runner)
|
|
2
|
+
|
|
3
|
+
The `mechbench` command: what you install on a machine to connect it to
|
|
4
|
+
[mechbench.ai](https://mechbench.ai). The repository keeps its old name
|
|
5
|
+
— the PyPI package and the command are `mechbench` (task 000307), and
|
|
6
|
+
the distribution ships two modules: `mechbench`, the bare front door,
|
|
7
|
+
and `mechbench_runner`, the engine it dispatches into.
|
|
8
|
+
|
|
9
|
+
The machine-side process of the [mechbench](https://mechbench.ai) family: it claims queued jobs from `mechbench-api`, executes them against `mechbench-compute`, and posts results back. It also exposes those same primitives as [Model Context Protocol](https://modelcontextprotocol.io) tools, so an LLM agent can call them directly.
|
|
10
|
+
|
|
11
|
+
**Status:** in use. `login` pairs a machine with an account; the runner then claims and executes jobs, reports progress and preparing steps, holds a live WSS channel for control and telemetry, and installs as a launchd or systemd service so it survives reboots. `doctor` tells you whether a machine will work before it tries. Three MCP tools (`run_protocol`, `get_result`, `list_jobs`) expose the same primitives to an agent.
|
|
12
|
+
|
|
13
|
+
## What this repo is for
|
|
14
|
+
|
|
15
|
+
Two adjacent surfaces for different callers:
|
|
16
|
+
|
|
17
|
+
1. **MCP server.** An LLM agent (Claude, others) connects via MCP stdio and calls mechbench primitives as structured tools. Tool bodies run in-process against `mechbench-compute`.
|
|
18
|
+
2. **Job-runner.** Polls `mechbench-api`'s `/jobs/next` for UI-queued protocols, runs them, posts results back. Same compute path as the MCP `run_protocol` tool; different *trigger*.
|
|
19
|
+
|
|
20
|
+
Both modes share one binary (`mechbench`) with subcommands; they share the loaded model, API client, and protocol executor. Splitting into separate processes is a later operational decision — see "Open design questions" below.
|
|
21
|
+
|
|
22
|
+
## Architectural decisions (task 000185)
|
|
23
|
+
|
|
24
|
+
- **Python.** `mechbench-compute` is Python; delegating to Python via RPC or subprocess-shell from a TS runner adds a layer that pays no dividends in v0. The MCP Python SDK is mature.
|
|
25
|
+
- **One binary, two subcommands.** `mechbench mcp` launches the MCP server over stdio; `mechbench run` starts the job-runner loop. They share `ExperimentRunner` (owns the loaded Gemma model) and `ApiClient`.
|
|
26
|
+
- **Agent authenticates to `mechbench-api` with a dedicated API key**, not a user's personal session. Export `MECHBENCH_API_KEY` (mint one at `/settings/api-keys`, or via `POST /auth/api-keys`). Matches the pattern from the e2e trace.
|
|
27
|
+
- **MCP `run_protocol` runs in-process**, not queued through `mechbench-api`. The MCP caller wants the answer; we are the compute target. Job-queue round-tripping exists for the *UI-triggered* path (job-runner subcommand).
|
|
28
|
+
- **stdio transport only.** SSE / HTTP-SSE transports earn their seat once remote MCP deploy matters (deferred).
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv tool install --managed-python mechbench
|
|
34
|
+
mechbench login
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`--managed-python` has uv fetch its own interpreter rather than adopt
|
|
38
|
+
whichever `python3` the machine happens to have. It costs a one-time
|
|
39
|
+
download and buys a version we support (3.11–3.14) on a machine whose
|
|
40
|
+
own Python we then never touch. `pipx install mechbench` works
|
|
41
|
+
too, against an interpreter you already have.
|
|
42
|
+
|
|
43
|
+
`login` prints a link and waits. Open it, approve the machine — the page
|
|
44
|
+
names it, along with its host and platform, before you do — and the
|
|
45
|
+
runner collects a credential it writes to `~/.mechbench/config.toml`
|
|
46
|
+
(mode 0600). Nothing durable passes through your hands: the code in the
|
|
47
|
+
URL grants nothing on its own, and the key is minted directly to the
|
|
48
|
+
machine that asked.
|
|
49
|
+
|
|
50
|
+
For a machine with no browser, `mechbench login --token mbr_…`
|
|
51
|
+
takes a single-use token minted at [mechbench.ai/download](https://mechbench.ai/download).
|
|
52
|
+
|
|
53
|
+
`login` then offers to start the runner automatically. Say yes and there
|
|
54
|
+
is nothing further to do: it starts at login, comes back after a crash,
|
|
55
|
+
and is controlled from the website.
|
|
56
|
+
|
|
57
|
+
### Updating
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
mechbench update
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Upgrades and restarts the service. **Re-running the install command does
|
|
64
|
+
not upgrade anything** — `uv tool install` treats an already-installed
|
|
65
|
+
tool as nothing to do and reports that in a way that reads like success,
|
|
66
|
+
so a machine can sit on an old version while looking freshly installed.
|
|
67
|
+
`update` verifies by reading the installed version back afterwards
|
|
68
|
+
rather than trusting an exit code, and rolls back if the new version
|
|
69
|
+
cannot start.
|
|
70
|
+
|
|
71
|
+
`mechbench doctor` answers "will this actually work here" —
|
|
72
|
+
Python, backend, credentials, API, model cache, disk — before you find
|
|
73
|
+
out the slow way.
|
|
74
|
+
|
|
75
|
+
Running a model needs Apple Silicon (the MLX backend from
|
|
76
|
+
`mechbench-compute`). The rest installs anywhere.
|
|
77
|
+
|
|
78
|
+
### Running it yourself
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
mechbench run # foreground, ^C to stop
|
|
82
|
+
mechbench install-service # or have the OS keep it running
|
|
83
|
+
mechbench service-status
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The service is supervised by launchd or systemd rather than by anything
|
|
87
|
+
we wrote — see `mechbench_runner/exits.py` for the contract that makes
|
|
88
|
+
that work.
|
|
89
|
+
|
|
90
|
+
**On macOS you will be told that software from "Ned Deily" can run in
|
|
91
|
+
the background.** That is this runner. macOS attributes a background
|
|
92
|
+
item to whoever code-signed the executable, and the executable is the
|
|
93
|
+
Python interpreter, which Ned Deily signs as CPython's macOS release
|
|
94
|
+
manager. Turning it off in Login Items & Extensions stops the runner;
|
|
95
|
+
`mechbench doctor` reports it if that happens.
|
|
96
|
+
|
|
97
|
+
### From a checkout
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/mechbench/mechbench-runner.git
|
|
101
|
+
cd mechbench
|
|
102
|
+
python3.11 -m venv .venv
|
|
103
|
+
source .venv/bin/activate
|
|
104
|
+
pip install -e '.[dev]'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Usage
|
|
108
|
+
|
|
109
|
+
### MCP server
|
|
110
|
+
|
|
111
|
+
Launch as a stdio MCP server — connect from Claude Desktop via `claude_desktop_config.json`:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"mechbench": {
|
|
117
|
+
"command": "/abs/path/to/mechbench/.venv/bin/mechbench",
|
|
118
|
+
"args": ["mcp"],
|
|
119
|
+
"env": {
|
|
120
|
+
"MECHBENCH_API_URL": "http://localhost:3000",
|
|
121
|
+
"MECHBENCH_API_KEY": "mbk_..."
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Three tools appear in Claude:
|
|
129
|
+
|
|
130
|
+
| tool | description |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `run_protocol` | Run a layer-ablation protocol in-process on a prompt; return per-layer damage. |
|
|
133
|
+
| `get_result` | Fetch a cached payload from `mechbench-api` by MechbenchPath. |
|
|
134
|
+
| `list_jobs` | List the caller's queued / running / completed jobs. |
|
|
135
|
+
|
|
136
|
+
### Job-runner
|
|
137
|
+
|
|
138
|
+
Polls `mechbench-api` for UI-queued jobs. Same compute path as `run_protocol`; different trigger.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
export MECHBENCH_API_URL=http://localhost:3000
|
|
142
|
+
export MECHBENCH_API_KEY=mbk_...
|
|
143
|
+
mechbench run
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Ctrl-C exits cleanly. API-unreachable is retried with exponential backoff capped at 30 s.
|
|
147
|
+
|
|
148
|
+
### In-process smoke test
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
mechbench smoke # quick: list_jobs + get_result
|
|
152
|
+
mechbench smoke --full # adds run_protocol (42 forwards, ~1-2 min)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Configuration
|
|
156
|
+
|
|
157
|
+
All via env vars:
|
|
158
|
+
|
|
159
|
+
| var | default | purpose |
|
|
160
|
+
|---|---|---|
|
|
161
|
+
| `MECHBENCH_API_URL` | `https://api.mechbench.ai` | mechbench-api base URL. Set it to `http://localhost:3000` to develop against a local API. Ignored when credentials are stored, which carry their own. |
|
|
162
|
+
| `MECHBENCH_API_KEY` | *(from `login`)* | Overrides the stored credential entirely, URL included. For CI and containers, which have nowhere to put a config file. |
|
|
163
|
+
| `MECHBENCH_POLL_INTERVAL_SECONDS` | `2.0` | Job-runner poll cadence. |
|
|
164
|
+
| `MECHBENCH_WARM_MODEL_ID` | *(none)* | Optional model to load at startup so the first job skips cold start. There is deliberately no default: a protocol names the model it runs against, and a job that names none is an error. |
|
|
165
|
+
| `MECHBENCH_WATCHDOG_SECONDS` | `900` | How long without progress counts as wedged. `0` disables it. |
|
|
166
|
+
|
|
167
|
+
## Relationship to other mechbench repos
|
|
168
|
+
|
|
169
|
+
- **`mechbench-compute`** — imported directly. `Model`, `Ablate`, hook-aware forward.
|
|
170
|
+
- **`mechbench-schema`** — produces `LayerAblationPayload` etc. as typed results.
|
|
171
|
+
- **`mechbench-api`** — the runner's only platform dependency. All workspace state (jobs, cache reads) goes through it.
|
|
172
|
+
- **`mechbench-ui`** — no coupling. UI queues jobs; the job-runner consumes them.
|
|
173
|
+
- **`mechbench-experiments`** — research scripts that use `mechbench-compute` directly, without the job machinery.
|
|
174
|
+
|
|
175
|
+
## Open design questions (deferred)
|
|
176
|
+
|
|
177
|
+
- **One binary or two processes?** Current answer: one binary, two subcommands. Revisit if MCP-caller frequency vs. job-runner throughput diverges enough to want independent scaling.
|
|
178
|
+
- **Structured-summary interface.** The family's philosophy doc describes a read-side surface where agents consume JSON summaries of findings / experiments. Currently implicit in `list_jobs` + `get_result`. A richer summary layer (`GET /summary`, `POST /query`) is still on the table but unbuilt.
|
|
179
|
+
- **MCP-surface observability.** Rate limits, per-tool metrics, audit trail for the tool-calling side. Deferred until a second LLM-agent consumer exists.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""The mechbench command.
|
|
2
|
+
|
|
3
|
+
Deliberately bare (task 000307): this module is the front door — the
|
|
4
|
+
`mechbench` entry point and its argument surface — and nothing else.
|
|
5
|
+
The machinery lives in `mechbench_runner`, which this package also
|
|
6
|
+
ships; the cli dispatches into it per command and imports none of it at
|
|
7
|
+
startup.
|
|
8
|
+
|
|
9
|
+
The boundary is drawn here on purpose. If engine releases ever outpace
|
|
10
|
+
this front door far enough that a supervisor should survive engine
|
|
11
|
+
upgrades untouched on disk, the split into two distributions happens
|
|
12
|
+
along exactly this line, with no further renaming.
|
|
13
|
+
"""
|