Repository navigation
io-cli 0.38.0 - #98
Merged
Merged
Conversation
EventKind::ToolCall gained origin: Option<Origin> in io-harness 0.77.0. non_exhaustive covers variants and not fields, so every exhaustive pattern and every struct literal breaks: four patterns take a trailing .., and thirty-three literals take origin: None. The field is not consumed. Drawing where a tool's output came from is a real feature and belongs to a release that argues it, not to this one as an aside. EventKind is 53 variants at 0.76.0 and 53 at 0.78.0, in the same order, so acp_map::MAPPING and triage::TRIAGE need no new row and the four variant count literals stay green. Task: US-IO-CLI-0.38.0-T01
…declared The variant arrived in io-harness 0.77.0 and the string appears nowhere in that crate's CHANGELOG, under Breaking or under Added. RunOutcome is non_exhaustive, so nothing failed to compile and three wildcards answered wrongly. exec::code exited UNFINISHED for a run that was judged. It belongs beside VerificationFailed by that variant's own argument: the work produced an answer, something checked it, and it did not hold up. io-harness makes the same distinction one layer down, saying that reporting a schema failure as a step cap would send an operator to raise max_steps, which buys more attempts at the same failure. exec::describe said the build had no name for it, and acp_map::stop_reason told an editor end_turn for a run that failed its schema; it now reports max_turn_requests, beside VerificationFailed. Reachable rather than theoretical: io-cli sets no output schema itself, but [run] output_schema is a configuration key that Config::apply_to applies, and both arms call it. Task: US-IO-CLI-0.38.0-T02
Three install paths now reach the same four artifacts: the scripts, a Homebrew tap and a scoop bucket. Each is updated by a different command, and a binary that cannot say which one placed it has made updating harder than the single-path release it replaced. io upgrade reads the running binary's own path and prints. It contacts nothing: asking GitHub for the latest version would need an HTTP client, which tests/dependencies.rs fails the build over, and running the upgrade would need a third permitted process spawn beside src/shell.rs and src/fetch.rs. Widening a set compared with == precisely so it cannot widen itself, to save an operator a copy and paste, is the worst trade available here. Homebrew is recognised by Cellar and by the prefix both, because current_exe does not promise a resolved path: Linux resolves through /proc/self/exe, macOS can return the symlink in bin. The comparison is on whole path components, never a substring, so a directory called scoop-notes is not a scoop install. An unrecognised path is told it is unrecognised. A guess presented as an instruction is how an operator ends up with two installs of one binary. The classification is a free function over a path, so every case is reachable from a test without installing anything, and one test spawns the real binary: nothing under tests/ links src/main.rs, and 0.30.0 shipped a documented io skill whose argv door answered unrecognized subcommand. Task: US-IO-CLI-0.38.0-T05
The Total section has drawn both the money floor and the cache-write floor
since 0.36.0. The per-model and per-day rows below it drew only the money
one, so a surface that states one floor stayed silent about the other and
reported an unknown as a fact.
Spend::unreported_cache_writes counts calls whose wire reported no
cache-write counter, exactly as unpriced_calls makes the money a floor. It
arrives by value on a struct grouped already holds, so no signature moved
and no harness call was added.
The vocabulary is section's, exactly: "{n} or more" for a mixed group,
"unknown" for a wholly silent one, and no qualifier when there is nothing
to qualify. Two surfaces on one page inventing two words for one fact is
the defect rather than the fix, so the test reads the value off the Total
section and requires the row to contain it.
Task: US-IO-CLI-0.38.0-T07
…ository io installed one way: a script piped from a URL. That is a checksum-verified, no-sudo, no-lifecycle-script path, and it is also the path a security-conscious developer's employer has told them not to take. The formula and the manifest point at the same four artifacts the installers already fetch, so nothing about distribution changes except how many ways there are to reach it: brew tap initorigin/io-cli https://github.com/initorigin/io-cli brew install initorigin/io-cli/io scoop bucket add io-cli https://github.com/initorigin/io-cli scoop install io Both files live here rather than in a dedicated tap repository. The cost is the explicit-URL form of brew tap, one longer line; the saving is two public repositories, a cross-repository push credential and two more things that can be red. scripts/update-tap.sh regenerates both from a published Release's own SHA256SUMS, so the digests are a function of the Release and never hand-copied. It reads all four before writing any byte, so a bad Release leaves both files untouched. The release workflow does not run it. main and develop both carry a pull_request ruleset whose only bypass actor is OrganizationAdmin, and Actions may not create pull requests, so automating this would need a granted bypass or a stored admin credential on a public repository. Neither is worth one merge click per release. There is no version stanza in the formula. Homebrew scans the version out of the url and brew audit --strict calls an explicit one redundant, which it is and worse: a second declaration of a fact the urls already carry can disagree with them. Task: US-IO-CLI-0.38.0-T04
…roval io acp refused every approval and told the client which action and why, so an editor driving io had to have its posture pre-configured or watch every write be denied. The frame builders for the request have existed since 0.36.0 with no production caller, and that module's own doc named what was missing: the correlation, not the design. io-harness publishes nothing for this. src/approve.rs is byte-identical across 0.76.0, 0.77.0 and 0.78.0, so the missing piece was this adapter's own loop. The reader now runs on its own task. serve_with awaited handler.handle() inline in its read loop, and for a session/prompt that call is the whole turn, so the client's answer to a question raised by that turn sat unread until the turn returned and the turn was waiting for the answer. That is a deadlock rather than a slow path, and it is the same shape as the writer starvation this function shipped one layer up. Responses are settled by the read task; requests and notifications queue for the loop, which is correct because ACP runs one turn per session. There is deliberately no approval timeout. Correlator::abandon runs when the reader stops, so a client that disconnects mid-question denies rather than hangs. A timeout would have been a number invented here: a minute is too short for someone reading a diff, and an hour is indistinguishable from a hang. approval::decision is now the one place an answer becomes a Decision, shared with the session's overlay, so "allow for this session" cannot come to mean a wider rule on one of the two surfaces than on the other. The tests assert the Decision the run receives and never that a frame was sent, and the mid-turn arm fails by hanging rather than by asserting. Task: US-IO-CLI-0.38.0-T06
adapt::generate ended with remove_dir_all(into) then rename(staging, into), and every door asked for consent after that returned. On a first install a decline was honest, because Prepared::made named the directory the install had created and unmake removed it. On an update made is None, so declining ran unmake(None) — which does nothing — over an adapter that had already been replaced. docs/guide/plugins.md has stated the opposite in writing since 0.35.0: that a refused refresh leaves the installed adapter exactly as it was. The page was the honest one, so the code moves to match it. generate now returns Adapter::staged and touches into on no path. Staged::commit is the swap and carries the old wipe-and-rename verbatim; Staged::discard removes the staging directory. marketplace::make and marketplace::unmake are the two acts, and src/main.rs holds wiring only. Prepared::made is gone rather than kept. It existed only to stop a decline deleting a pre-existing adapter, and once the swap moved behind the answer a decline reaches into in neither case, so the install/re-install distinction has no consequence left. Disclosing the staged adapter surfaced a second defect: pluginview::detail draws contributed directories as whole absolute paths, so the operator would have been shown a hidden .x.staging.<pid> path contradicting the "copied into" row on the same screen. adapted_disclosure re-roots them from Plugin::root() onto the destination. F13 and F14 are a pair, and each says so: a fix that makes declining safe by making accepting a no-op passes F13 alone. Task: US-IO-CLI-0.38.0-T08
Found by the adversarial diff review, behind a fully green suite.
Consulting held an AtomicU32 it constructed at zero and only ever read —
nothing ever stored it — so every permission frame named cell
{run_id}-0 whatever step raised it, while acp_map builds a cell's id from
the event's own step.
Through 0.37.0 that mis-addressed a tool_call_update on a call that had
already failed. From 0.38.0 it would mis-address the dialog an operator
acts on, attaching the question to a call that had already finished, on
every approval after the first step of a turn.
The step now comes from the observer, which is the only thing in this
module that sees one: an Approver is handed a Request carrying an act and a
target and no step at all. Reporter records it before translating, and
unconditionally, because an event that draws nothing still moved the run
on.
The regression gate asserts the id against acp_map's own toolCallId for the
same event rather than against a literal, so the two cannot drift into two
spellings of one id.
Task: US-IO-CLI-0.38.0-T06
This crate cites io-harness source as path.rs:LINE. tests/docs.rs's f19
checks that a citation naming a version names the pinned one; it does not
check the line, and an unversioned citation names no version and is
invisible to it. So the lines have never been checked by anything.
They were three generations deep. Some anchored to io-harness 0.69-era
numbers, some 0.74-era, some 0.76-era — proved by finding each claim exact
in an older tree: fn read_instructions sits at 1872 in 0.69.0, 2680 in
0.74.0, 2799 in 0.76.0 and 2911 in 0.78.0.
That is why this is not an arithmetic shift. Applying one uniform offset
would have moved a wrong number to a different wrong number and laundered
staleness into the appearance of currency. Every citation was re-derived by
content against the 0.78.0 source instead.
Two corrections are not line numbers at all. provider/mod.rs:1745 pointed
into a doc example whose body is Ok(false), the opposite of the
async { Ok(true) } the comment quotes. And PROJECT_WIDENING was described
as refusing five pairs when it refuses twelve — 0.74.0 added
policy.defaults.read/write, workspace-write and five sandbox.limits
zero-caps. A mirrored table gone stale, which is the class 0.35.0 paid for.
A second layer nobody had swept sat in state/memory.rs, where fifteen
citations pointed into doc comments rather than the code they name — one at
a blank line, one inside memory_similar for a claim about memory_pin.
Task: US-IO-CLI-0.38.0-T03
Two install paths that no page mentioned, a subcommand missing from the contract page, and three statements the release falsified. README gains the brew tap and scoop bucket lines and an io upgrade paragraph. Its standing non-goal sentence — that io contacts no server it was not asked to — stays true and gains a clause, because io upgrade reads a path rather than a network. The installer scripts are untouched: their stdout is pinned at exactly sixteen lines by tests/installers.rs, and the right place for a new sentence is the page, not the narration. docs/CONTRACT.md gains the io upgrade row and has its permission section rewritten. It said an ACP approval is refused and that routing an answer back into the run is not wired; both stopped being true in this release. docs/guide/editors.md said the same at length. docs/RELEASE_PROCESS.md gains step 10, the tap update, with the reason the workflow cannot do it: main and develop both carry a pull_request ruleset whose only bypass actor is OrganizationAdmin, and Actions may not create pull requests here. release.yml's Install block, welded into every Release, named only the two scripts. docs/guide/accounting.md now states the cache-write floor beside the money one. AGENTS.md's module map said src/ holds 79 files; it holds 82. docs/guide/plugins.md needed no edit. It already described the behaviour T08 made true, and the code moved to match the page. Task: US-IO-CLI-0.38.0-T09
Two arms, and the second is what makes the first mean anything. An editor client speaks to a real io acp child over its real stdin and stdout, asks for a file to be written under a write = "ask" posture, answers the session/request_permission it gets, and the assertion is whether the file exists afterwards. Allowing writes it; denying does not. Without the second arm, a model that wrote the file without ever being asked would pass the first — which is the shape 0.34.0 shipped, a live arm passing over a feature that placed nothing because the model reached the goal another way. Through the binary, because nothing under tests/ links src/main.rs: an adapter that worked in the library and was never reached by the subcommand would pass every offline arm. Task: US-IO-CLI-0.38.0-T10
io-cli 0.38.0
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
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.
The release.
develop→main, tree identical to the one every gate ran on (git diff --quiet feat/0.38.0 develop).io installs from the package manager a developer already has — a Homebrew formula and a scoop manifest served from this repository, pointing at the same four checksum-verified artifacts the installers already fetch.
io upgradereads the running binary's own path and prints the command that updates it, contacting nothing.Three published limitations stop being true:
io acpasks the editor for permission instead of denying every approval,/cost's grouped rows state the cache-write floor, and declining a bundle re-install leaves the adapter byte-identical.io-harness 0.76.0 → 0.78.0, which carried a breaking change that crate's changelog never declared:
RunOutcome::SchemaUnsatisfiedbehind anon_exhaustiveenum, so a schema-failed run exited5instead of6and told editorsend_turn.Verification
cargo test --all-targets— 107 binaries, 1,955 passed, 0 failed, 38 ignoredRecord sealed at
sha256:8d1449daa4a404610f998bf682666e9aaf977039cdc549b88b317809848f122e, before this merge..ultraship/is gitignored, so it is on disk and not in this history.The tap and the bucket are updated after the Release is cut — they name a published
SHA256SUMS, so the artifacts do not exist until the tag builds them.