feat(toolbox): the seven outbox writers get their own door -- row 1 moves 8 -> 15 of 17
Every one of the run path's seven `outbox.write_*` steps was reachable only through `run.main`, and every path through that builds a chat client. The steps need no model: they take already-rendered data and put it on disk in a byte-deterministic form. Seven subcommands, seven thin adapters. The outbox directory is always the caller's to name -- never a default, never the repository's own, because a step that wrote into a folder the framework also reads as an inbox would bypass the Step-8 promotion gate. `write-outbox` is the one that is not purely mechanical: `outbox.write_outbox` branches on the outcome TYPE, so a door that took the outcome as an argument would let anyone author an outbox of claims and hand it to Step 8 as results. The door DERIVES it through `validate_proposal` -- the run path's own composition -- and a blocked proposal exits 3 with the artefacts still written, since that is where the rejection is recorded. `verdict_id` stays an argument: `verdict-key` already owns that minting. `--stop-reason` is required rather than defaulted to the empty string, inheriting the core writer's measured reason: "the run finished" and "we never found out" must not be the same value. Eight probes, each a subprocess with the subcommand in argv, each asserting on the FILE the command wrote. The ground truth is composed in the test -- the payload it wrote and counted itself, and the byte form the contract requires -- never `outbox._dump`, which would have measured the module against itself. The refusal arm carries its rc-0 control. Measured, own run of the B gate: row 1 8 of 17 -> 15 of 17, exit 1 unchanged, no other row moved. 0 chat-client names reachable from the toolbox (known-positive control: 24 in run.py). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1111924000
commit
6375ce5af3
5 changed files with 691 additions and 30 deletions
22
README.md
22
README.md
|
|
@ -113,8 +113,30 @@ uv run portfolio-optimiser-toolbox verdict-key --proposal <proposal.json>
|
|||
# Mint an expert's judgement into the Verdict the store holds (stdout is the on-disk form)
|
||||
uv run portfolio-optimiser-toolbox capture-verdict --proposal <proposal.json> \
|
||||
--decision approved --rationale "why"
|
||||
|
||||
# Write the run's artefacts. Seven writers, one subcommand each — the outbox directory is always
|
||||
# yours to name, never a default: a run must not write into a folder it also reads as an inbox.
|
||||
uv run portfolio-optimiser-toolbox write-run-config --out-dir <dir> --run-id <id> \
|
||||
--profile local --resolved-models <roles.json> \
|
||||
--max-rounds 5 --max-tokens 600000 --top-k 3
|
||||
uv run portfolio-optimiser-toolbox write-outbox --outbox-dir <dir> --run-id <id> \
|
||||
--proposal <proposal.json> --provenance <stamp.json> --verdict-id <key>
|
||||
uv run portfolio-optimiser-toolbox write-coverage --outbox-dir <dir> --run-id <id> \
|
||||
--rows <rows.json> --stop-reason ""
|
||||
uv run portfolio-optimiser-toolbox write-prepass --outbox-dir <dir> --run-id <id> \
|
||||
--declaration <cut.json>
|
||||
uv run portfolio-optimiser-toolbox write-parse-failures --outbox-dir <dir> --run-id <id> \
|
||||
--failures <failures.json>
|
||||
uv run portfolio-optimiser-toolbox write-proposal-reviews --outbox-dir <dir> --run-id <id> \
|
||||
--payload <reviews.json>
|
||||
uv run portfolio-optimiser-toolbox write-debate-tools --outbox-dir <dir> --run-id <id> \
|
||||
--tool-calls <calls.json> [--requirements <requirements.json>]
|
||||
```
|
||||
|
||||
`write-outbox` does not take the outcome — it DERIVES it, by running the proposal through the
|
||||
same blocking gate the run path runs it through, and exits `3` when that gate says no. An outbox
|
||||
whose verdicts the caller could declare would be a collection of claims, not of results.
|
||||
|
||||
Each subcommand calls the same function the run path calls — not a copy of it. That is what makes
|
||||
the answers you get here the answers the debate gets: a proposal a human wrote meets the same
|
||||
stages, in the same order, with the same sentence, as one an agent produced.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue