Repository navigation
fix: a CLI run ends with the CLI, and list cells take pasted JSON - #52
Merged
Merged
Conversation
…e its pipes A run read the CLI's output to the end before it waited for the CLI to exit. A program the CLI started that held its output open and outlived it (a credential helper's background process) kept the run going until Studio's timeout, holding the one CLI turn for 30 s or more. The run now waits for the exit beside the reads. Once the CLI has ended, its pipes are read for 250 ms more, long enough to deliver what it wrote.
A list parameter read JSON (`["a","b"]`, the form a list value is copied in) or comma-separated items, but a list cell, form field or bulk edit read only the comma form, so a copied list pasted into a cell was refused. One reader, `input::list_texts`, reads both for cells and parameters. It also covers `[]`, so the special case for an empty list goes.
…iler finds the clause The gateway decides from tokens alone whether a mutation is written `as commit` or `as unattached branch`, so text the compiler cannot parse is not let through unread. Its test now pins that, wherever the compiler's parse finds the clause, the gateway refuses, and that where neither finds it, both let the write through.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 13fb56b. Configure here.
| let status = match exited { | ||
| Some(status) => status, | ||
| None => child.status().await, | ||
| } |
There was a problem hiding this comment.
Pipes stay open past read bound
Medium Severity
A pipe that hits its read bound no longer closes. The Take wrappers now outlive the reads and stay open through child.status(), so a command that writes past the bound can fill the OS pipe and block. That holds the CLI turn until the outer timeout, instead of ending once the bound is read.
Reviewed by Cursor Bugbot for commit 13fb56b. Configure here.
ragnorc
added a commit
that referenced
this pull request
Nov 1, 2026
…lists (#54) * fix(cli): close each pipe at its read limit, and filters read pasted lists A review of #52 found that its change kept a CLI's pipes open after their read limit: the `Take` wrappers lived until the run ended. A CLI that wrote more than its limit plus a pipe buffer (an oversized token) then blocked on a full pipe and never exited, so the run ran out the timeout instead of being refused at once, holding the CLI turn. Each read now owns its pipe and closes it at the limit, keeping what it read. The test of a program left holding the pipes sleeps a minute and allows 30 s, with room for macOS to scan a new script on its first run. The "is one of" filter says it reads a list as a list cell does, but it kept the comma-only reader when cells took JSON. It now uses the same `list_texts`, so a copied list pasted into a filter works too. * fix(cli): say an over-long token is too long, and leave pasted lists uncompleted An export answer longer than a token fills the read bound without its newline and is now refused as too long, instead of as whatever the closed pipe made of it. The leaving-process test gets room to fail on a slow runner without timing out. A filter list typed as JSON is no longer completed, since a pick would rewrite it as items.
ragnorc
added a commit
that referenced
this pull request
Nov 1, 2026
…lists A review of #52 found that its change kept a CLI's pipes open after their read limit: the `Take` wrappers lived until the run ended. A CLI that wrote more than its limit plus a pipe buffer (an oversized token) then blocked on a full pipe and never exited, so the run ran out the timeout instead of being refused at once, holding the CLI turn. Each read now owns its pipe and closes it at the limit, keeping what it read. The test of a program left holding the pipes sleeps a minute and allows 30 s, with room for macOS to scan a new script on its first run. The "is one of" filter says it reads a list as a list cell does, but it kept the comma-only reader when cells took JSON. It now uses the same `list_texts`, so a copied list pasted into a filter works too.
ragnorc
added a commit
that referenced
this pull request
Nov 1, 2026
…lists A review of #52 found that its change kept a CLI's pipes open after their read limit: the `Take` wrappers lived until the run ended. A CLI that wrote more than its limit plus a pipe buffer (an oversized token) then blocked on a full pipe and never exited, so the run ran out the timeout instead of being refused at once, holding the CLI turn. Each read now owns its pipe and closes it at the limit, keeping what it read. The test of a program left holding the pipes sleeps a minute and allows 30 s, with room for macOS to scan a new script on its first run. The "is one of" filter says it reads a list as a list cell does, but it kept the comma-only reader when cells took JSON. It now uses the same `list_texts`, so a copied list pasted into a filter works too.
ragnorc
added a commit
that referenced
this pull request
Nov 1, 2026
…lists A review of #52 found that its change kept a CLI's pipes open after their read limit: the `Take` wrappers lived until the run ended. A CLI that wrote more than its limit plus a pipe buffer (an oversized token) then blocked on a full pipe and never exited, so the run ran out the timeout instead of being refused at once, holding the CLI turn. Each read now owns its pipe and closes it at the limit, keeping what it read. The test of a program left holding the pipes sleeps a minute and allows 30 s, with room for macOS to scan a new script on its first run. The "is one of" filter says it reads a list as a list cell does, but it kept the comma-only reader when cells took JSON. It now uses the same `list_texts`, so a copied list pasted into a filter works too.
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.


Three last items from the wider review that #50 and #51 left open. Based on main (6216514) and independent of #51.
A CLI run ends when the CLI does (
graph_store)A run read the CLI's output to the end before it waited for the CLI to exit. A program the CLI started that held its output open and outlived it (a credential helper's background process, for example) kept the run going until Studio's timeout. That held the one CLI turn for 30 s or more. The run now waits for the exit beside the reads. Once the CLI has ended, its pipes are read for 250 ms more, long enough to deliver what it wrote.
A list cell takes a list pasted in JSON (
gq_language)A list parameter read JSON (
["a","b"], the form a list value is copied in) or comma-separated items. A list cell, form field or bulk edit read only the comma form, so a copied list pasted into a cell was refused. One reader,input::list_texts, now reads both for cells and parameters. It also covers[], so the special case for an empty list goes.The gateway's held-clause rule beside the compiler's (
agent_panel, test only)The gateway decides from tokens alone whether a mutation is written
as commitoras unattached branch, so that text the compiler can't parse isn't let through unread. Its test now pins two things: wherever the compiler's parse finds the clause, the gateway refuses; where neither finds it, both let the write through.Testing
cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspace(1,166 passed) and the repo checks pass locally, on top of the current main.cli_tokens::tests::input_a_command_does_not_read_ends_at_its_timeout(extended with a script that leaves a background process holding its output) andinput::tests::a_list_reads_back_as_it_was_written(extended with pasted JSON) both fail without their fixes (checked).Checked and left
pubfunction in the workspace is named only where it's defined, and no crate has an unused dependency. The one hit,studio_theme'sutil, is there for itsdebug-embedfeature.Note
Medium Risk
Changes how Studio waits on Omnigraph CLI subprocess I/O (affects token export and CLI turn duration), plus shared list parsing for edits and parameters.
Overview
CLI subprocess handling no longer blocks until stdout/stderr pipes close.
run_onceraces pipe reads against process exit; after the CLI exits, pipes are drained for 250 ms so output is captured without waiting on detached helpers (e.g. credential helpers). A regression test covers a script that backgrounds a long sleep while printing a token.List property input is unified through new
list_texts: bracket-leading text is parsed as JSON (as when copying a list value), otherwise comma-separated items as before. Form cells and query parameters both use this path; the separate empty-list shortcut inparse_inputis removed. Tests cover pasted["a", "b"]and reject null elements.Gateway mutation tests only: held vs allowed
as commitcases are named arrays, with assertions thatheld_off_the_branch(token scan) aligns with the compiler’sdeclared_writeparse wherever both apply.Reviewed by Cursor Bugbot for commit 13fb56b. Bugbot is set up for automated code reviews on this repo. Configure here.