Repository navigation
io-cli 0.30.2 - #78
Merged
Merged
Conversation
AGENTS.md carries the commands CI actually runs, the architecture map, the three exact-path rules tests/dependencies.rs enforces, and the tests that gate prose. CLAUDE.md points at it rather than restating it, so the conventions have one place to be wrong in rather than two.
STYLE.md extends io-harness's register with the surface a library does not have: text the binary prints at a person mid-task. RELEASE_PROCESS.md records why the order is an order — the seal before the merge, the tree check before the release PR, the tag alone, and a smoke that exercises the release's own surface rather than the version string.
A library's contract is its API; a tool's is the argv it accepts, the codes it exits with, the keys it reads and the paths it writes. Enumerates all four, plus the limits that hold today — including that IO_CONFIG_HOME does not move the skills directory, which 0.30.1 found and nothing had written down.
The unknown-verb arm listed mcp, plugin and config, so `io skill bogus` fell through to the unknown-surface arm and answered "`skill` is not a surface io manages; they are `mcp`, `plugin`, `skill` and `config`" — a sentence that denies and asserts the same fact and never names the verbs. The bare-surface arm beside it already listed all four, which is what makes it an oversight. Nothing in the suite read a refusal's words for this family; the gate does now, per surface rather than over a joined string.
SECURITY.md forbade opening a public issue and then named a literal <project-contact-email>, and CODE_OF_CONDUCT.md carried the same token, so from 0.1.0 to 0.30.1 this project told people not to open an issue and gave them nowhere else to go. The README routes every report at SECURITY.md, so the dead end was the only documented path. Both now point at GitHub's private reporting on this repository. Two gates: one that no shipped markdown leaves a contact placeholder, one that the replacement route is really named — the first alone is satisfied by deleting the section.
Written before the guide pages exist, so the orphan half is RED until T07 lands the split. That is deliberate: its non-empty assertion is load-bearing, because with no pages on disk both loops iterate nothing and the test would pass while proving nothing — the vacuous-gate shape this repository has shipped four times. The link half is green now, which is what proves the checker itself works. A link check is a few lines of std; adding a markdown crate to a tree held at ten direct dependencies to find a missing file would be the expensive answer to the cheap question.
…s not a trap The plugin path example used a tilde, and no tilde is expanded for a [[plugin]] path — io-harness resolves env:, file: and cmd: and nothing else, so the bundle names a directory literally called ~ and is dropped: recorded by the loader, listed by /plugin, otherwise silent. The same file forbids tildes 130 lines earlier. Also adds [toolchain], three more [run] keys with the remaining five named in prose, and [[mcp]]'s url, headers and timeout_secs; corrects the PriceTable reason (0.71.0 gave it models/len/is_empty — the conclusion survives, the stated reason did not) and the policy-layering mechanism, which is strictest-effect first across all layers rather than layer order. The gate requires a line an operator could uncomment rather than contains(), because run, test, build and format are English words appearing throughout the prose.
The largest: the home is one directory only until you name a location of your own — io.toml, the store and IO.md follow IO_CONFIG_HOME while the skills directory, marketplaces and the session lock do not; /mcp does offer a disable, because McpServer gained enabled in io-harness 0.70.0 and this crate already writes it; two modules start a process, not one; a bundle contributes to six subsystems, not four; exit 6 has two routes since the 0.71.0 pin, not one; and io skill reached the binary in 0.30.1, not 0.30.0. Counts nothing checks are deleted rather than corrected — the undrawn event kinds were wrong in the README and in exec.rs's own doc comment, in two different ways. The CHANGELOG had 33 version headings and 3 link definitions, so 30 rendered as literal text while the header claimed Keep a Changelog conformance. That half is mechanical, so it is now asserted rather than reviewed.
… that ships /contain is in Group::Session and was documented under "this turn", so the printed table showed eleven rows against a bound of ten the same page states. The existing gate checked every name, every description and the total, and all three were true — a row in the wrong table is still a row. The new gate joins a command to its heading through Group::title(), the string the palette draws. The install section still described 0.29.0: write enabled = false, re-discover, disclose off the result. 0.30.0 replaced that with Plugins::inspect, so a reader was told their configuration is written to before they consent, when declining now writes no byte at all. Both halves are asserted — the prose alone would pass if the feature were ripped out, the code alone would pass while the prose stayed wrong.
The README was a 2,847-line manual with no contents list. It is now a front page — logo, screenshot, what you get, install, first run, a guides table — and nineteen pages under docs/guide/ carrying the depth, indexed a second time by docs/CAPABILITIES.md so neither index can be the only way in. The split was done by moving byte ranges rather than by rewriting, and the line accounting was checked: 2,695 moved, 175 kept, 2,870 total. No paragraph was reworded on the way. Fifteen gates in tests/docs.rs read a README that no longer carries their claims, and every one of them went RED rather than quiet, which is the outcome the release was designed around. Each now names the page that carries its claim. The two NEGATIVE sweeps are the ones that could have gone vacuous — !contains is satisfied by any file that never mentioned the subject — so they read every present-tense page instead of one file. CHANGELOG.md is excluded from those sweeps by name. A changelog is a diary: its 0.16.0 entry records a limitation that was true when written, and sweeping it for present-tense truth would force history to be rewritten whenever the product moved.
… copy A contract page is the one document a script author depends on, so a wrong exit code or a missing key there is worse than no page. All three halves ask the code: exit codes from exec's constants, subcommands from clap itself, and the [app.io-cli] keys read out of CliSettings' own source — so a field added without a row fails rather than arriving undocumented. The spelled key count is asserted too, because a number in prose is exactly what goes stale: this release found the README claiming thirty-nine undrawn event kinds when there were fifteen.
Bumps the crate version, writes the release entry, and exempts the changelog from the placeholder sweep. That exemption earned itself: this release's own entry has to quote <project-contact-email> in order to say it was removed, and the gate failed on that sentence. A gate that reads prose can forbid a file from explaining itself — the third time this repository has hit that shape — and the changelog is the one file whose job is to describe what used to be there.
io-cli 0.30.2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release PR for 0.30.2.
A documentation release: thirty-one claims across the README, changelog, contributing and security policies, configuration reference and shipped skills did not survive being checked against the code that decides them. Two were live code defects.
Security:
SECURITY.mdforbade opening a public issue and then gave a literal<project-contact-email>as the alternative — no way to report a vulnerability at all, since 0.1.0. Both it andCODE_OF_CONDUCT.mdnow route through GitHub's private vulnerability reporting.Fixed:
io skill <bad-verb>answered a sentence that denied and asserted the same fact; the bundle example used a tilde where none is expanded, so a copied path yielded a silently dropped bundle.Changed: the 2,847-line README is now a front page plus nineteen guide pages under
docs/guide/, withdocs/CONTRACT.md,docs/CAPABILITIES.md,AGENTS.md,docs/STYLE.mdanddocs/RELEASE_PROCESS.mdadded. The split moved byte ranges rather than rewriting — 2,695 moved, 175 kept, 2,870 accounted for.Added: nine gates, including link/orphan integrity and a contract page compared against
exec's constants,clap's routing table andCliSettings' fields.Gates on the feature PR (#77): 8/8 green across macOS, Linux, Windows and MSRV. Suite 98 binaries / 1,619 passed / 0 failed / 36 ignored; doctest 1 passed; clippy
-D warningsand fmt exit 0. A sabotage arm was executed for every functional criterion.git diff --quiet feat/0.30.2 developis clean, so this is the tree the gates ran on.