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.
Files changed (46) hide show
  1. mechbench-0.5.0/PKG-INFO +214 -0
  2. mechbench-0.5.0/README.md +183 -0
  3. mechbench-0.5.0/mechbench/__init__.py +13 -0
  4. mechbench-0.5.0/mechbench/cli.py +334 -0
  5. mechbench-0.5.0/mechbench.egg-info/PKG-INFO +214 -0
  6. mechbench-0.5.0/mechbench.egg-info/SOURCES.txt +44 -0
  7. mechbench-0.5.0/mechbench.egg-info/dependency_links.txt +1 -0
  8. mechbench-0.5.0/mechbench.egg-info/entry_points.txt +2 -0
  9. mechbench-0.5.0/mechbench.egg-info/requires.txt +11 -0
  10. mechbench-0.5.0/mechbench.egg-info/top_level.txt +2 -0
  11. mechbench-0.5.0/mechbench_runner/__init__.py +12 -0
  12. mechbench-0.5.0/mechbench_runner/_smoke.py +72 -0
  13. mechbench-0.5.0/mechbench_runner/api_client.py +247 -0
  14. mechbench-0.5.0/mechbench_runner/channel.py +405 -0
  15. mechbench-0.5.0/mechbench_runner/config.py +102 -0
  16. mechbench-0.5.0/mechbench_runner/control.py +543 -0
  17. mechbench-0.5.0/mechbench_runner/credentials.py +157 -0
  18. mechbench-0.5.0/mechbench_runner/doctor.py +317 -0
  19. mechbench-0.5.0/mechbench_runner/exits.py +32 -0
  20. mechbench-0.5.0/mechbench_runner/install.py +217 -0
  21. mechbench-0.5.0/mechbench_runner/job_runner.py +437 -0
  22. mechbench-0.5.0/mechbench_runner/login.py +402 -0
  23. mechbench-0.5.0/mechbench_runner/logs.py +182 -0
  24. mechbench-0.5.0/mechbench_runner/machine.py +48 -0
  25. mechbench-0.5.0/mechbench_runner/mcp_server.py +120 -0
  26. mechbench-0.5.0/mechbench_runner/models_cmd.py +82 -0
  27. mechbench-0.5.0/mechbench_runner/paths.py +28 -0
  28. mechbench-0.5.0/mechbench_runner/service.py +304 -0
  29. mechbench-0.5.0/mechbench_runner/supervisor.py +252 -0
  30. mechbench-0.5.0/mechbench_runner/updater.py +244 -0
  31. mechbench-0.5.0/mechbench_runner/watchdog.py +107 -0
  32. mechbench-0.5.0/pyproject.toml +76 -0
  33. mechbench-0.5.0/setup.cfg +4 -0
  34. mechbench-0.5.0/tests/test_channel.py +248 -0
  35. mechbench-0.5.0/tests/test_control.py +182 -0
  36. mechbench-0.5.0/tests/test_credentials.py +173 -0
  37. mechbench-0.5.0/tests/test_doctor.py +240 -0
  38. mechbench-0.5.0/tests/test_install.py +144 -0
  39. mechbench-0.5.0/tests/test_logs.py +36 -0
  40. mechbench-0.5.0/tests/test_pipeline_jobs.py +45 -0
  41. mechbench-0.5.0/tests/test_promotion.py +116 -0
  42. mechbench-0.5.0/tests/test_service.py +193 -0
  43. mechbench-0.5.0/tests/test_signed_out.py +116 -0
  44. mechbench-0.5.0/tests/test_supervision.py +142 -0
  45. mechbench-0.5.0/tests/test_supervisor.py +137 -0
  46. mechbench-0.5.0/tests/test_updater.py +171 -0
@@ -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
+ """