feat(tasks): minimal interactive runtime rework with segment rwlock#8473
feat(tasks): minimal interactive runtime rework with segment rwlock#8473
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a focused rework of the task execution runtime to support interactive tasks. It adds an Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces support for interactive tasks by adding an interactive flag and managing concurrent execution with a global RwLock. Non-interactive tasks acquire a read lock, while interactive tasks acquire a write lock, ensuring exclusive access to the terminal when needed. The changes also include TTY validation for interactive tasks, proper terminal state restoration for raw-mode commands, and PID tracking for improved signal handling. The implementation is well-structured and includes thorough unit tests for the new concurrency logic. I have reviewed the changes and found no issues.
Greptile SummaryThis PR adds an Key issues:
The core interactive lock semantics are sound and unit tests are well-structured with deterministic channel-based synchronization. However, both the user-facing hint message and the Confidence Score: 2/5
Sequence DiagramsequenceDiagram
participant CLI as CLI (run.rs)
participant Exec as TaskExecutor
participant Lock as TASK_RUNTIME_LOCK<br/>(tokio RwLock)
participant Cmd as CmdLineRunner
participant RAW as RAW_LOCK<br/>(std RwLock)
participant Child as Child Process
Note over CLI,Child: Non-interactive task
CLI->>Exec: exec_program(task.interactive=false)
Exec->>Lock: acquire read lock
Lock-->>Exec: read guard held
Exec->>Cmd: execute() [raw=false]
Cmd->>RAW: acquire read lock
RAW-->>Cmd: read guard held
Cmd->>Child: spawn + wait (piped I/O)
Child-->>Cmd: exit
Cmd-->>Exec: Ok(())
Exec-->>CLI: Ok(())
Note over CLI,Child: Interactive task
CLI->>CLI: validate_task → is_terminal() check
CLI->>Exec: exec_program(task.interactive=true)
Exec->>Lock: acquire WRITE lock (blocks new readers)
Lock-->>Exec: write guard held
Exec->>Cmd: execute() [raw=true → execute_raw()]
Cmd->>RAW: acquire WRITE lock
RAW-->>Cmd: write guard held
Cmd->>Child: pre_exec (setpgid if non-TTY) + spawn
Note over Cmd: save TTY state (tcgetattr)
Cmd->>Child: wait()
Child-->>Cmd: exit
Note over Cmd: restore TTY state (tcsetattr)
Cmd-->>Exec: Ok(())
Note over Exec: drop write guard → unblocks readers
Exec-->>CLI: Ok(())
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a minimal “interactive task” execution model by adding an interactive task flag and enforcing exclusive access to the runtime segment (write lock) for interactive tasks while allowing concurrent non-interactive tasks (read lock).
Changes:
- Add
interactive: boolto the task model, config parsing, schemas, and JSON outputs (tasks info/ls, MCP payload). - Enforce TTY-on-stdin for interactive tasks and run them with inherited stdio.
- Add a global async runtime segment
RwLockto serialize interactive runtime execution vs concurrent non-interactive execution, with targeted unit tests.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/task/task_executor.rs | Adds global runtime segment lock (rwlock), interactive stdio/TTY behavior, and unit tests for locking/stop-check ordering. |
| src/task/mod.rs | Adds Task.interactive field, header parsing, default value, and parsing test expectation updates. |
| src/config/config_file/mise_toml.rs | Adds unit tests validating interactive TOML deserialization and type enforcement. |
| src/cmd.rs | Adjusts raw execution to restore tty state and track raw PIDs; adds unix pre_exec process-group tweak. |
| src/cli/tasks/ls.rs | Includes interactive in mise tasks ls --json output. |
| src/cli/tasks/info.rs | Includes interactive in mise tasks info --json output. |
| src/cli/run.rs | Validates interactive tasks require a TTY on stdin before running. |
| src/cli/mcp.rs | Adds interactive to MCP mise://tasks payload. |
| schema/mise.json | Adds interactive to task schemas. |
| schema/mise-task.json | Adds interactive to task schemas. |
| e2e/tasks/test_task_ls | Updates JSON expectations to include interactive: false. |
| e2e/tasks/test_task_info | Updates JSON expectations to include interactive: false. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
66e699c to
2811348
Compare
|
@greptileai review |
2811348 to
b4acc27
Compare
|
The We reverted This PR re-introduces The comment says "Keep raw-mode process group behavior aligned with non-raw execution in non-tty contexts" but the non-raw My recommendation: drop the If there's a specific signal-handling problem that This comment was generated by Claude Code. |
b4acc27 to
4e7a455
Compare
|
Thanks for scoping However, there's still a logical issue: the I'd suggest just removing the The TTY save/restore and PID tracking additions in This comment was generated by Claude Code. |
|
look just stop, it's clear to me you don't understand the code you're trying to write. We need to be very careful around this logic. |
|
@jdx You're right about the setpgid — I had an automated fixup loop pushing without manual review on each iteration. That specific mistake is on me. That said, I want to share some honest context on this whole process. I've submitted 5 PRs over several weeks to fix a real regression — TTY tasks are broken since the scheduler rework, and this affects real workflows (ie: saml2aws → interactive tools in the same DAG). Each time, I got short feedback asking for something simpler, but without enough detail on what the target implementation should look like. I went from a static DAG planner, to a dynamic policy, to a semaphore barrier, to a segment RwLock — each one a genuine attempt to match what I understood you wanted. I know TTYs, DAGs, and schedulers well. What I don't know well is the internal history of every code path in cmd.rs, and I didn't get enough direction to avoid these specific pitfalls. The setpgid/#8347 context wasn't something I could have inferred without guidance. Since the implementation is this sensitive to internal context, I'd welcome you taking it from here. What matters most to me is fixing this TTY regression that affects your users (my team included). |
|
I'm not going to argue about it but your PRs are the most slop I've ever received on this project. |
) ## Summary - Adds `interactive = true` task field that acquires an exclusive write lock on a global `RwLock`, giving the task sole access to stdin/stdout/stderr - Non-interactive tasks use a shared read lock and continue running in parallel with each other - More targeted alternative to `raw = true` which forces `jobs=1` globally — `interactive` only blocks concurrent tasks while the interactive task is running - Supersedes #8473 with a much simpler approach: no `cmd.rs` changes, no TTY save/restore, no setpgid ## Changes - `src/task/mod.rs` — add `interactive: bool` field, file-task parsing, default - `src/task/task_executor.rs` — global `TASK_RUNTIME_LOCK: RwLock<()>`, acquire write (interactive) or read (non-interactive) before `cmd.execute()` - `src/task/task_output_handler.rs` — treat `interactive` as `raw` for I/O - `src/cli/tasks/info.rs`, `src/cli/tasks/ls.rs`, `src/cli/mcp.rs` — add `interactive` to JSON output - `schema/mise-task.json`, `schema/mise.json` — add `interactive` boolean property - `e2e/tasks/test_task_info`, `e2e/tasks/test_task_ls` — update expectations ## Test plan - [x] `mise run lint-fix` passes - [x] `cargo test` — all 520 unit tests pass - [x] `mise run test:e2e test_task_info test_task_ls` passes - [x] Manual test: `interactive-task ::: bg-task-1 ::: bg-task-2` — interactive task waits for exclusive access while bg tasks run in parallel 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches core task execution/concurrency and terminal I/O behavior via a new global lock, which could introduce deadlocks or unexpected scheduling/throughput changes if edge cases aren’t covered. > > **Overview** > Adds a new boolean task field `interactive` (default `false`) that marks a task as requiring exclusive terminal access, and wires it through task parsing and defaults. > > Task execution now uses a global runtime `RwLock` to coordinate concurrency: interactive tasks take an exclusive lock (including during confirmation prompts), while non-interactive tasks take a shared lock; the lock is held across consecutive run-script entries but dropped while waiting on injected sub-tasks to avoid deadlocks, and command execution is wrapped in `block_in_place` to avoid starving the tokio runtime. > > CLI/MCP JSON outputs and `tasks info` property display now include `interactive`, JSON schemas (`mise.json`, `mise-task.json`) are updated accordingly, interactive tasks are treated as raw I/O in the output handler (with a new hint warning about redactions), and e2e expectations are updated. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4126daa. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
This PR implements a minimal interactive runtime rework for tasks, intentionally scoped to avoid the complexity explored previously.
What’s included
Add
interactivetask metadata (true|false, defaultfalse):mise.tomlmise tasks info --jsonmise tasks ls --jsonmise://taskspayloadKeep scheduler/
--jobsbehavior aligned with currentmain:Add one global async runtime lock in task execution:
is_stopping()) happens immediately after lock acquisition, before executing the runtime segmentInteractive runtime behavior:
stdin/stdout/stderr = inherit)Non-goals intentionally not implemented
acquire_many_owned(max_permits)--jobs=1mixed runtime+injection behavior in this PRTests
Added unit tests
config::config_file::mise_toml::tests::test_tasks_interactive_deserialize_true_and_default_falseconfig::config_file::mise_toml::tests::test_tasks_interactive_rejects_non_booltask::task_executor::tests::test_stop_check_happens_after_runtime_lock_acquisitiontask::task_executor::tests::test_interactive_segment_uses_write_lock_and_blocks_readersUpdated existing e2e expectations
e2e/tasks/test_task_info(includesinteractive: falsein JSON expectation)e2e/tasks/test_task_ls(includesinteractive: falsein JSON expectation)Validation run
cargo fmt --allcargo check -qcargo test -qNotes
This PR supersedes #8464 with a narrower, lower-risk implementation aligned to the minimal spec.