Skip to content

io-cli 0.37.0 - #96

Merged
aakashpawar1999 merged 3 commits into
mainfrom
develop
Sep 4, 2026
Merged

aakashpawar1999 merged 3 commits into
mainfrom
develop

Conversation

@aakashpawar1999

Copy link
Copy Markdown
Contributor

Release PR for 0.37.0.

/context attributes the tool catalogue to what put it on the wire — a row per MCP server named with its bundle, and a skill catalogue row for the block io-harness writes into the system prompt, which four releases had counted inside system block so a session's skills appeared to cost nothing. /plugin and /mcp state the same figure where the thing is switched on. /context withhold <tool> withholds a tool until it is allowed again, as verbs under an existing command — COMMANDS.len() is still 36.

The roadmap's premise was false and correcting it is most of the release. io-harness 0.76.0's ToolMask is availability, never membership: a masked run is offered a byte-identical catalogue, deliberately, because the tool array sits ahead of the provider's cache breakpoint. The mask adds a sentence rather than removing definitions. Attribution is the cost feature; masking is a scoping one, and a prose gate over every shipped page stops the original framing returning.

The adversarial review found three High and four Medium behind a fully green suite — a withheld misspelling silently withholding nothing, the skill catalogue swallowing io-harness's planning directive on every contained turn, /plugin drawing a real zero before any turn, and server_of taking the first prefix match. Each fixed with a regression test verified to fail when reverted.

The live gate found the most useful thing: the mask arm failed against a working mask, because io-harness announces a withholding before the model acts so a compliant model never produces the refusal the criterion named. The arm now asserts the guarantee and is proved by a negative control.

  • Suite 105 binaries / 1,929 passed / 0 failed / 38 ignored
  • Live 37/37 in 1,152s plus the mask arm and its control
  • PR io-cli 0.37.0 #95 green on all 8 checks including the three-platform matrix
  • ultraship validate exit 0 over 118 checks; record sealed and pinned before the merge
  • io-harness stays at 0.76.0 — first release in eighteen where the pin does not move
  • Four iteration records

… for a turn

/context drew the tool catalogue as one number, so an operator who wanted to know
which of their bundles was expensive had no way to ask. It is now attributed: a row
per MCP server named with the bundle that contributed it, and a skill catalogue row
for the block io-harness writes into the system prompt — which until now was counted
inside the system block, so a session's skills appeared to cost nothing at all.

/plugin and /mcp draw the same figure on the row where the thing is switched on,
from the same snapshot, so the two surfaces cannot disagree. The tiers are stated
from a table keyed by io-harness's own wire names rather than from a hand-written
list: of the seven kinds of thing a bundle contributes, only skills, agents and MCP
servers reach the wire.

/context withhold <tool> takes a tool away from the next turn and /context allow puts
it back — verbs under an existing command, so COMMANDS.len() is still 36 and the last
free group slot stays free.

A mask does not make a turn cheaper, and the code says so everywhere it could be
misread. io-harness offers a masked turn a byte-identical catalogue on purpose,
because the tool array sits ahead of the provider's cache breakpoint and dropping a
definition would pay a cache write on every later turn. Withholding in fact adds one
sentence naming the withheld tools. The roadmap entry this version was planned from
assumed the opposite; attribution is the cost feature and masking is a scoping one.

Suite: 105 binaries, 1,924 passed, 0 failed, 37 ignored. fmt and clippy clean.
…n suite

Two reviewers split by area found disjoint sets and both were load-bearing.

A withheld name that answers to nothing was confirmed as refused. io-harness keeps an
unknown mask entry rather than rejecting it, deliberately, so that a mask stays portable
across builds with different cargo features — which means `mask_gate` matches on the exact
string and a misspelling withholds nothing. `/context withhold Docx_Write` printed "calling
it will be refused before anything starts", drew the name on the withheld row, and left the
tool fully callable. The asymmetry was the tell: the allow arm already refused to be a
silent no-op and was tested for it, so the guard existed only on the harmless direction.
The name is still added — refusing it here would break the portability io-harness designed
for — and the sentence now says it matches nothing on the wire.

The skill catalogue swallowed io-harness's planning directive. `compose` appends the
directive with `push_str` and `Skills::catalog()` ends with no trailing newline, so the
final catalogue line on the wire carries the whole directive and still starts with "- ".
The row over-reported by roughly 117 tokens and, worse, `bundle_cost` charged those tokens
to whichever bundle owns the alphabetically last skill — so a bundle's figure moved when
the operator toggled `/plan`, for a reason that had nothing to do with it. Reachable on
every contained turn, and invisible to the partition test because the bytes are inside
`request.system` either way.

`/plugin` drew "0 tokens every request" for every bundle before any turn had run, while
`/mcp` correctly drew "not yet on a request" for the very server one of them contributed.
A zero on that column says the bundle is free, which is the one claim that stops an
operator looking. The costs are now attached only when a request has actually gone out.

`server_of` took the first prefix match rather than the longest, so a configured `github`
absorbed every tool belonging to `github__enterprise` and the enterprise server read as
unmeasured for the life of the session.

Also: the docs taught `/context allow` as the inverse of a single withhold when bare allow
clears the whole mask; CONTRACT.md still said all eleven mid-turn commands report; the
verbs were absent from `/help`, the palette and the command guide; and every sentence said
"the next turn" for what is a standing posture.

Each fix has a regression test, and each test was verified to fail when its fix is reverted.

Suite: 105 binaries, 1,929 passed, 0 failed, 38 ignored. Live 37/37 in 1152s, plus the new
mask arm proved by a negative control — without the mask the model calls write_file
immediately; with it, no write_file step ever commits and the run routes around.
@aakashpawar1999
aakashpawar1999 merged commit b4bada8 into main Sep 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant