picocode executes a tool side effect after SIGINT cancellation
- Dominant language
- Rust
- Stars
- 61
- Forks
- 3
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
picocode can continue consuming a delayed provider tool call after a user interrupt has already been delivered, execute the local tool side effect, and then fail after repeated tool-result submissions.
The standalone reproducer downloads public `picocode v0.6.0`, starts a local mock provider, schedules `SIGINT` 500 ms after the CLI starts, delays the provider tool call for 1200 ms, and verifies that the delayed tool call still writes a marker file after cancellation.
## Affected target
- Target: `jondot/picocode`
- Affected version checked with the public reproducer: `0.6.0`
- Current public latest checked on 2026-06-22: GitHub release `v0.6.0`
- Environment: Linux x86_64 Docker, public release asset
- Provider/model: local OpenAI-compatible mock provider, `gpt-4o-mini`
## Steps to reproduce
Prerequisites: Docker, Python 3, and the GitHub CLI (`gh`) for the clone command below. The linked reproducer is self-contained and uses only Python standard-library modules plus Docker. It downloads the affected public Linux release asset, starts a local mock provider, and runs the CLI in an isolated workspace. The Docker run is limited to 2 CPUs and 4 GiB RAM by default.
Complete self-contained reproducer: https://gist.github.com/N0zoM1z0/dd743067a7c080031558cd00c7cdf2e2
The Gist contains `picocode-late-effect-after-cancel.reproduce.py`. Download and run:
```bash
gh gist clone dd743067a7c080031558cd00c7cdf2e2 picocode-late-effect-after-cancel-reproducer
cd picocode-late-effect-after-cancel-reproducer
python3 picocode-late-effect-after-cancel.reproduce.py
```
To reuse an already-built local image:
```bash
python3 picocode-late-effect-after-cancel.reproduce.py --skip-build
```
Expected successful reproduction output includes:
```text
provider_requests_at_least: observed=10 expected>=1
tool_result_after_signal: observed=45 expected>=1
side_effect_file_contains picocode-late-effect-after-cancel.log 'late-effect-after-signal': observed=True
REPRODUCED
```
## Actual behavior
picocode receives `SIGINT` before the delayed provider tool call is emitted, but it still executes the later shell tool side effect and repeatedly submits tool results for `late_after_cancel`. The public reproducer then exits with a bounded `MaxDepthError`.
## Expected behavior
After user cancellation, picocode should stop consuming later provider-stream tool calls and should not execute their local side effects.
Public upstream status: This report targets stock public `picocode v0.6.0` from the GitHub release asset. This is separate from the child-process cleanup report because it validates cancellation semantics.
Contributor guide
No contributing guide indexed for this repository
Research direction
Run picocode-late-effect-after-cancel.reproduce.py first to confirm the delayed provider-stream behavior. Then trace the CLI cancellation path through provider tool-call consumption and shell-tool execution. Done means later tool calls are not consumed or executed after SIGINT, tool results are not repeatedly submitted, and the reproducer no longer reports the late side effect.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100