Metadata-Version: 2.4
Name: stallguard
Version: 0.1.0
Summary: Drop-in wrapper that streams agent steps and kills/flags stalls, loops, and fake-GOAL finishes.
License: MIT
Project-URL: Homepage, https://github.com/gpt4omni/stallguard
Keywords: ai-agents,llm,coding-assistant,devtools,cli
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# stallguard

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](pyproject.toml)
[![No dependencies](https://img.shields.io/badge/deps-zero-brightgreen.svg)](stallguard/)
[![CI](https://github.com/gpt4omni/stallguard/actions/workflows/test.yml/badge.svg)](https://github.com/gpt4omni/stallguard/actions/workflows/test.yml)

**Your coding agent says "done". Did it do anything?** stallguard is a drop-in
wrapper that streams agent steps, kills stalls and retry-loops, and flags
fake-GOAL finishes — with a shareable trace for every run.

![stallguard demo](demo.gif)

```bash
pipx install stallguard
stallguard run -- npx claude-code "fix the login bug"
# [stallguard] status=ok exit=0 duration=42.1s trace=traces/stallguard-....html
```

No code changes. Just prefix your agent command with `stallguard run --`.

## The problem

AI coding agents fail in three boring, expensive ways:

1. **Stalls** — no output for 20 minutes while your CI minute-burn ticks.
2. **Loops** — the same tool call retried 500 times (`retrying with same args...`).
3. **Fake-GOALs** — prints `DONE ✅` while `git diff` is empty.

Logs scroll by, nobody watches, green checkmarks lie. stallguard turns each run
into a verdict: `ok`, `error`, `stalled`, `looped`, or `fake-goal` — enforced
by exit code, so CI can act on it.

## 30-second quickstart

```bash
# any agent, any command — just prefix it
stallguard run -- python -u your_agent.py
stallguard run --stall-timeout 90 --require-diff -- ./run.sh

# inspect a run later
stallguard view traces/stallguard-*.jsonl
# open traces/stallguard-*.html in a browser for the full step-by-step trace
```

## What it catches

| flag | default | catches | exit |
|---|---|---|---|
| `--stall-timeout N` | 120 | no output for N seconds → `SIGKILL` | 124 |
| `--repeat-limit K` | 15 | K identical lines in a row → `SIGKILL` | 125 |
| `--require-diff` | off | exit 0 + "done" text but empty `git diff` | 3 |
| `--expect-file PATH` | — | required file missing after run (repeatable) | 3 |
| `--trace-dir DIR` | `traces` | JSONL + summary JSON + self-contained HTML per run | — |

`0` = ok, `1` = agent errored, `3` = fake-goal, `124` = stalled, `125` = looped.

## Why not just `timeout`?

`timeout 300 ./agent` kills a hung run but tells you nothing: was it a stall, a
loop, or nearly done? And it can't catch the worst case — the agent that
finishes fast, prints success, and changed zero files. stallguard records
*timestamped evidence* for every run and verifies the goal actually happened.

## CI: fail on fake success

```yaml
- name: Run agent under stallguard
  run: stallguard run --stall-timeout 300 --require-diff -- ./run-agent.sh
- name: Upload traces
  uses: actions/upload-artifact@v4
  with:
    name: stallguard-traces
    path: traces/
```

Or use the bundled composite action (see [action.yml](action.yml)).
Every failed run links its HTML trace — debugging starts from evidence, not
from re-running and hoping.

## Works with any agent

`stallguard` sees stdout, not APIs, so it works with everything:
Claude Code, Codex CLI, OpenHands, AutoGPT, your own Python script — if it
prints steps, stallguard can supervise it. Zero dependencies, stdlib only.

## Dev

```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
python -m stallguard run -- python -u examples/ok.py
python -m stallguard run --stall-timeout 1 -- python -u examples/hang.py; echo $?
python -m stallguard run --repeat-limit 3 -- python -u examples/loop.py; echo $?
python -m unittest discover -s tests
```

## Roadmap

- [ ] Token/step budgets (`--max-lines`, `--max-minutes`)
- [ ] Semantic loop detection (same tool call, different formatting)
- [ ] Live web dashboard for parallel agent fleets
- [ ] PyPI release + Homebrew formula

PRs welcome — especially real traces of agents failing in new and creative ways.

MIT. If stallguard caught your agent slacking, leave a ⭐.
