Conversation
`resolve_solver_case` resolves one file or one serialized PowerIO IR document into a typed module, selects a collection entry by `time_index` or `scenario_id`, and hands a writer the balanced network an operating point states. `OperatingPoint.network` supplies that network directly, so no MATPOWER round trip narrows the state to a representable subset. `pio-ir` and `pio` are the format tokens PowerIO accepts; a document carrying neither is refused on PowerIO's own terms. Diagnostics follow PowerIO's severity vocabulary: `error` fails validation, `remark` and `note` stay out of the user-facing warning list. `check_diagnostics`, `operating_point_module` and `select_entry` are public because a second server module calls them. `value_type_name` isolates the one structural-type read PowerIO publishes no accessor for. `powermcp.sandbox` re-exports `staged_file_write` alongside the rest of the path policy and states powerio's containment default. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pandapower, PyPSA, ANDES, Egret and surge accept `powerio_ir` as the primary argument, keep `network_json` as its alias, and splice the shared response tail: `value_type`, `selection`, `diagnostics`, `warnings`, plus the emission fidelity and the typed-edit report for the adapters that convert into their own model. PowerIO 0.11.2 hands a directory writer a path that does not exist yet, so the PyPSA CSV export and the surge table export create the staging directory before writing into it. ANDES and Egret install their one emitted case file through `staged_file_write`, so a write that fails part way leaves whatever stands at the destination untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fourteen declarations now read `powerio[mcp,matrix]>=0.11.2,<0.12`. The floor is 0.11.2 because 0.11.1 added `OperatingPoint.network` and matrix `row_ids`, and 0.11.2 sets the path-containment default this repository documents. `GenX/requirements.txt` gains a pin: `GenX/server.py` imports `powermcp.sandbox`, which imports powerio. Version 0.4.0. The sdist excludes local virtual environments and uv build caches, and `.gitignore` covers `.venv-*/`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PowerIO 0.11.2 confines MCP paths to the directory the process started in when no root variable names one. A session-scoped autouse fixture names the repository checkout, pytest's temporary base and the system temporary directory, so a test writing under `tmp_path` is admitted. A test that sets its own roots still overrides it, because `allowed_roots()` reads the environment on every call. `_containment_status` distinguishes an explicit root list from the implicit default, reports the default as a setting to make rather than a policy already chosen, and reports the refusal PowerIO raises for a root variable naming no directory. The doctor's user-visible strings carry no decorative characters. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The powerio and solver-boundary tests require powerio 0.11.2, so the matrix tools name their axes unconditionally and a retired Package document is asserted for what it is: not PowerIO IR. `tests/test_transport.py` states why it exists. The SDK parses a string argument whose text is JSON before validation, so only a real stdio session proves a `powerio_ir` argument reaches the tool intact. `tests/test_sdk_imports.py` covers PLEXOSDB, the one server directory it missed. `tests/test_publish_workflow.py` asserts the sdist exclude list keeps local virtual environments and build caches out of a release. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The PowerIO section describes the server shipped in 0.11.2, names the arguments every adapter takes, and states the containment default: with no root variable set, paths stay beneath the directory the server process started in. Per-server READMEs describe what the import tools accept, which is serialized PowerIO IR or one selected entry of a collection. The retired `Package`, `model-json`, `package_json` and package `study_commit` formats keep their migration note: re-parse the original case and pass its `powerio_ir`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
stdout carries JSON-RPC once a server runs, so the ANDES startup notes go to its logger, which writes to stderr, and the two PowerWorld error reports go to stderr explicitly. `GenX/server.py` keeps the repository root on `sys.path` for the process lifetime and says why: GenX carries no `__init__.py`, so its namespace `__path__` is recomputed from `sys.path` on every attribute lookup and the lazy `GenX.tool_logic` imports would fail without it. PLEXOSDB's notes on its shared import name say what the module is: a re-export of the `plexosdb-mcp` server object under that same name. The install picker's instruction line and the `powermcp` package docstring carry no decorative characters. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powerio 0.11.2 ships a cp39-abi3 manylinux wheel serving Python 3.9 through 3.14, and the only other Rust dependency, surge-py, lives in an opt-in extra CI never installs. Without the toolchain step a future wheel gap fails loudly instead of building from an sdist. The suite spawns roughly forty subprocesses per job with 60 second timeouts, so stacked pushes on a busy runner turn a timeout into a failure. The concurrency group cancels superseded pull request runs and leaves pushes to main alone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powermcp/tellegen.py exchanges PowerIO IR with the tellegen binary over stdin and stdout: the powerio server parses, Tellegen solves, and the solution comes back as a PowerIO module every other tool reads. The tools are capabilities, contract, solve, solve_module, plan and the Study family. Applying a Study proposal binds a recommendation to the Study and stays a human action, so study_run refuses it. The binary resolves from POWERMCP_TELLEGEN_BINARY, then the tellegen.binary config key, then PATH. A multiconductor value and a module PowerIO marks with an error are both refused before the process starts. The tellegen extra is empty because the CLI is a Rust binary rather than a pip package. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The binary is not a Python package, so the import probe says nothing about it. The doctor runs the configured executable's capabilities subcommand and reports green only when it exits zero and prints JSON. Output decodes as UTF-8 with replacement so a non-UTF-8 console cannot raise UnicodeDecodeError. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tests/data/fake_tellegen.py stands in for the compiled binary and speaks the same JSON protocol, so CI needs no Rust toolchain. One test runs against a real build and skips unless TELLEGEN_BIN names one. The checked-arguments table in tests/test_sandbox.py lists the three helpers every tellegen tool reaches the filesystem through, and test_windows_only_flags names tellegen among the servers that run everywhere. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
powermcp/TELLEGEN.md covers configuration, the Study bundle format, revision binding and cancellation. The README section states how to build the CLI, point PowerMCP at it, and read the response tail, and the PowerIO section names Tellegen as a consumer of the same IR. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The matrix now covers the floor of requires-python and every version the classifiers claim, so a regression on a newer interpreter fails the run instead of reaching users through a claim the tests never check. The full suite passes unchanged on both added versions: powerio ships abi3 wheels, and the core tests substitute fakes for the vendor engines. The checkout and setup-python steps move to their current major tags. README and the package guide state the tested range rather than an open floor, matching the classifiers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Landed on I cherry-picked your commit ( One thing worth checking, which I deliberately did not silently 'fix' for you: the three-way merge of your branch would have kept Also flagging a small pre-existing inconsistency, since your commit comment now reads "every version the classifiers claim": 3.11 is in the classifiers but not in the matrix. Not introduced here, and I left it alone. Closing as merged-by-cherry-pick — reopen if you'd rather land it as the branch once #67 resolves. |
Summary
requires-pythonand every version the classifiers claim.Stacked on #67, which stacks on #64; draft until those merge.
Testing
Full suite from the branch root, no code changes needed on either new interpreter (
powerioinstalls from its abi3 wheel):🤖 Generated with Claude Code