-
v1.2.0 Stable
released this
2026-09-20 12:46:28 +00:00 | 14 commits to main since this releaseThe release that opens the run path to callers who are not this framework. Every path through the
CLI builds a debate, and therefore a chat client; the steps the debate is built on need no model
at all, and this release gives each of them a command of its own.Added
portfolio-optimiser-toolbox(portfolio_optimiser.toolbox), a third console command beside the
CLI and the offline demo. Fourteen subcommands, each a thin adapter over the function the run
path itself calls, never a second implementation:navigate-bundle,cost-baseline,
retrieve-chunks,prepass-admit,validate-proposal,verdict-key,capture-verdict,
write-run-config,write-coverage,write-outbox,write-prepass,write-parse-failures,
write-proposal-reviewsandwrite-debate-tools. No model call and no network on any of them;
JSON on stdout; exit0the step ran,2the call was malformed,3the step refused and the
refusal is named. A proposal the deterministic validator blocks is also3, and carries the
verbatim reason and the stage rather than an exception envelope.- The outcome an outbox records is derived, never supplied by the caller:
write-outboxruns
the proposal through the same blocking gate the run path uses, because a door that accepted the
outcome as an argument would let anyone author an outbox of assertions. The outbox directory is
always the caller's to name, and--stop-reasonis required - "finished" and "never found out"
are different runs. - A measurement gate for the whole surface (
python -m portfolio_optimiser.evals.b_gate): which
run-path steps are callable from outside, proved by a probe that executes the door and asserts on
data that came back from it. Fifteen of seventeen steps at this release; the round binder and its
report share one module entry point without a subcommand that tells them apart.
Security
- A caller-supplied name that carries a path is refused by all seven outbox doors before
anything is written. Each writer composes<out_dir>/<name>-<artefact>.json; the directory was
guarded and the names were not, so--outbox-dir <d>/inni --run-id ../../Xwrote two levels
above the directory the caller named and answered0. Separators, a bare.or.., an
absolute prefix, an embedded NUL and the empty string are now refused with exit3, the reason
named, and no directory left behind. The class is every caller-supplied value that reaches a
file name, not one flag:write-outboxcomposes<run_id>-<approach_id>, and
--approach-id a/../../../Xescaped the same way through the other half of that stem. Both go
through one rule. - Containment as the last link: a composed artefact path that does not resolve under the
output directory is refused, inoutboxitself, where all eleven compositions are built and
before the directory is created. The string rule above lives in the door, so this one covers the
callers that never pass a door - the run path hands its own--run-idstraight to these writers- and the next value someone interpolates into a file name.
Fixed
--stop-reasonbeing required is now guarded by a test rather than only by prose. The rule is
load-bearing - "the run finished" and "we never found out" must not be the same value - but
swappingrequired=Truefordefault=""passed the entire suite before this release.
Changed
- Console entry points are pinned against the installed distribution's metadata rather than
againstpyproject.toml: a[project.scripts]line that has never been installed is a claim,
not a command.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads