Metadata-Version: 2.4
Name: loopgrade
Version: 0.1.0
Summary: Autonomous dependency upgrader powered by LangGraph and LLMs
License: MIT
Project-URL: Homepage, https://github.com/Sagar-S-R/loopgrade
Project-URL: Repository, https://github.com/Sagar-S-R/loopgrade
Keywords: dependency,upgrade,langgraph,llm,cli,automation
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: langgraph>=0.2.0
Requires-Dist: langchain-groq>=0.1.0
Requires-Dist: langchain-google-genai>=1.0.0
Requires-Dist: typer>=0.12.0
Requires-Dist: rich>=13.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: packaging>=24.0
Requires-Dist: requests>=2.31.0

# loopgrade

> Autonomous dependency upgrader powered by LangGraph and LLMs.
> Upgrades your dependencies one at a time, runs your tests, commits what works, reverts what breaks — without you touching anything.

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![LangGraph](https://img.shields.io/badge/powered%20by-LangGraph-purple.svg)](https://github.com/langchain-ai/langgraph)

---

## The Problem

You have a project with 20 dependencies. Half of them are outdated. Running `ncu -u` or `pip install --upgrade` upgrades all of them at once — and when something breaks, you have no idea which package caused it.

So you don't upgrade. The deps rot. Security patches pile up.

loopgrade fixes this.

It upgrades **one dependency at a time**, runs your test suite after each upgrade, commits if it passes, reverts if it fails, and moves on to the next one. When it's done, it gives you a full report of what was upgraded, what failed, and why.

---

## How It Works

loopgrade is built on [Loop Engineering](docs/loop_engineering.md) — the practice of designing autonomous systems that work toward a goal without human prompts. Instead of you babysitting an AI agent turn by turn, loopgrade designs the loop once and lets it run.

The core loop is a [LangGraph](https://github.com/langchain-ai/langgraph) StateGraph — a stateful, cyclical graph that carries a shared state object through every node. Each node reads what it needs from state, does one job, and writes back only what changed.

**[See docs/agent.md](docs/agent.md)** for the full agent architecture diagram, node descriptions, tool definitions, and LLM prompts.

---

## Conflict Resolution

Version conflicts are detected **before** any file is touched — not discovered after tests fail.

### How conflicts are detected

For npm, loopgrade runs:
```bash
npm install axios@1.7.2 --dry-run
```

For pip:
```bash
pip install numpy==2.0.0 --dry-run
```

Both commands hit the resolver without touching anything on disk.

### Three outcomes

**`none`** — no conflicts, proceed to upgrade normally.

**`resolvable`** — a constraint exists but a safe version is available. Example: you want `numpy 2.0.0` but `scipy 1.11.0` requires `numpy < 2.0`. loopgrade finds `numpy==1.26.4` (the highest version satisfying all constraints) and uses that instead of the absolute latest. The result is logged as "upgraded with adjustment."

**`hard`** — no version of the package can satisfy all constraints simultaneously. loopgrade skips it immediately — zero test attempts wasted — and logs the exact reason plus a suggestion for what the developer should do manually.

### What a hard conflict looks like in the report

```markdown
## Failed / Skipped
- webpack: 4.46.0 → 5.91.0
  reason: hard conflict — html-webpack-plugin 4.x requires webpack<5
  suggestion: upgrade html-webpack-plugin to 5.x first, then retry webpack
```

---

## Retry Policy

Each dependency gets up to 3 attempts. The retry logic is intelligent — not just "try the same thing again."

```
Attempt 1 → try absolute latest version
              ↓ fail
Attempt 2 → try safe_version from resolver (if available)
              ↓ fail
Attempt 3 → try one minor version below latest
              ↓ fail
→ skip + flag for manual review
```

**Early exit conditions** — these skip the dep immediately, no attempts wasted:

- `same_error_streak >= 3` — identical error across retries means retrying is pointless
- `conflict_info.type == "hard"` — mathematically impossible, skip before any attempt
- `retry_count >= max_retries_per_dep` — out of attempts

**Global hard cap** — `max_iterations` in config (default: 20). When hit, the run ends regardless of how many deps remain. This is your cost guardrail — no surprise LLM bills from infinite loops.

---

## The State Report

loopgrade writes `loopgrade-state.md` to your project root after every single dependency — win, lose, or skip. You can open it any time during a run and see live progress:

```markdown
# loopgrade run — 2026-07-07 14:32

## Progress: 3/8 deps processed

## Upgraded 
- lodash: 4.17.19 → 4.17.21
- express: 4.17.1 → 4.18.2

## Upgraded with adjustment 
- numpy: 1.24.0 → 1.26.4 (wanted 2.0.0, constrained by scipy==1.11.0)
## Failed / Skipped 
- webpack: 4.46.0 → 5.91.0
  reason: hard conflict — html-webpack-plugin 4.x requires webpack<5
  suggestion: upgrade html-webpack-plugin to 5.x first, then retry webpack
- axios: 0.27.0 → 1.7.2
  reason: 3 attempts failed — response structure migration needed in code
  suggestion: update all axios call sites to use new response format before upgrading

## Remaining
- dotenv, jest, eslint, prettier, typescript
```

---

## Installation

### Prerequisites

- Python 3.10+
- Git initialized in your project (`git init`)
- Your test suite must pass before running loopgrade (`npm test` or `pytest` exits 0)
- For npm projects: `npm-check-updates` installed globally (`npm install -g npm-check-updates`)
- A Groq or Gemini API key (both have free tiers)

### Install loopgrade

```bash
pip install loopgrade
```

Or install from source:

```bash
git clone https://github.com/yourusername/loopgrade
cd loopgrade
pip install -e .
```

---

## Quick Start

```bash
# 1. go to your project
cd my-project

# 2. initialize loopgrade (creates config + .env)
loopgrade init

# 3. add your API key to .env
echo "GROQ_API_KEY=your_key_here" >> .env

# 4. run it
loopgrade run
```

> **Note:** The default configuration assumes a Node.js project (`npm test`). If you are using Python, be sure to edit `loopgrade.config.json` and change `"package_manager": "pip"` and `"test_command": "pytest"` (or whatever you use for testing) before running `loopgrade run`.

That's it. loopgrade will scan your deps, upgrade them one at a time, and report back.

---

## CLI Reference

### `loopgrade init`

Creates `loopgrade.config.json` and `.env` in your current directory with sensible defaults.

```bash
loopgrade init
```

### `loopgrade run`

Runs the full autonomous upgrade loop.

```bash
loopgrade run                          # standard run
loopgrade run --dry-run                # show what would be upgraded, no changes
loopgrade run --only axios             # upgrade one specific package
loopgrade run --config path/to/config  # use a different config file
```

**Before starting**, loopgrade validates:
- A git repo exists in the current directory
- Your test suite currently passes (if tests are already failing, loopgrade won't run — fix them first)

### `loopgrade status`

Pretty-prints the current `loopgrade-state.md` with rich formatting.

```bash
loopgrade status
```

---

## Configuration Reference

`loopgrade.config.json` — place this in your project root.

```json
{
  "llm_provider": "groq",
  "model": "llama-3.3-70b-versatile",
  "max_iterations": 20,
  "max_retries_per_dep": 3,
  "package_manager": "npm",
  "test_command": "npm test",
  "skip_major_versions": false,
  "skip": []
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `llm_provider` | string | `"groq"` | LLM provider to use. Options: `"groq"`, `"gemini"` |
| `model` | string | `"llama-3.3-70b-versatile"` | Model name. See provider docs for options |
| `max_iterations` | int | `20` | Hard cap on total iterations across all deps. Your cost guardrail |
| `max_retries_per_dep` | int | `3` | Max attempts per dependency before skipping |
| `package_manager` | string | `"npm"` | Package manager. Options: `"npm"`, `"pip"` |
| `test_command` | string | `"npm test"` | Command loopgrade runs to verify each upgrade |
| `skip_major_versions` | bool | `false` | If true, skip any dep with a major version bump |
| `skip` | array | `[]` | List of package names to skip entirely e.g. `["react", "typescript"]` |

---

## Environment Variables

Create a `.env` file in your project root (loopgrade reads it automatically):

```bash
# use one of these depending on your configured provider
GROQ_API_KEY=your_groq_key_here
GEMINI_API_KEY=your_gemini_key_here
```

**Getting API keys:**
- Groq (recommended — fast, cheap, generous free tier): [console.groq.com](https://console.groq.com)
- Gemini: [aistudio.google.com](https://aistudio.google.com)

---

## Supported Package Managers

| Package manager | Dep file | Install command | Test discovery |
|----------------|----------|-----------------|----------------|
| npm | `package.json` | `npm install` | configured via `test_command` |
| pip | `requirements.txt` | `pip install -r requirements.txt` | configured via `test_command` |

More package managers (yarn, pnpm, poetry, cargo) are planned — contributions welcome.

---

## Why loopgrade over just running `ncu -u`?

| | `ncu -u` | loopgrade |
|--|----------|-----------|
| Upgrades all deps at once | Yes | — |
| Tests after each upgrade | — | Yes |
| Reverts on failure | — | Yes |
| Attributes which dep broke things | — | Yes |
| Detects version conflicts before trying | — | Yes |
| Finds safe version ceiling for conflicts | — | Yes |
| Explains why something failed | — | Yes |
| Suggests manual steps for hard failures | — | Yes |
| Your codebase always left in working state | — | Yes |

---

## Project Structure

```
loopgrade/
├── loopgrade/
│   ├── cli.py                  # typer CLI — run / init / status
│   ├── config.py               # load + validate loopgrade.config.json
│   ├── agents/
│   │   ├── __init__.py
│   │   ├── graph.py            # LangGraph graph assembly + routing
│   │   ├── state.py            # LoopgradeState TypedDict
│   │   └── nodes/
│   │       ├── __init__.py
│   │       ├── scan.py         # scan_deps node
│   │       ├── pick.py         # pick_next node
│   │       ├── upgrade_node.py # upgrade_node — pre-upgrade LLM call
│   │       ├── upgrade.py      # run_upgrade node
│   │       ├── test.py         # run_tests node
│   │       ├── verifier_node.py# verifier_node — post-test LLM call
│   │       ├── commit.py       # commit_success node
│   │       ├── revert.py       # revert_dep node
│   │       ├── skip.py         # skip_dep node
│   │       ├── state_writer.py # write_state node
│   │       ├── conflict_check.py
│   │       └── conflict_resolve.py
│   │
│   ├── tools/
│   │   ├── registry.py         # get latest versions from npm / PyPI
│   │   ├── files.py            # edit package.json / requirements.txt
│   │   ├── runner.py           # run install + test commands
│   │   ├── git.py              # commit / revert
│   │   └── conflicts.py        # dry-run conflict detection + safe version finder
│   │
│   └── providers/
│       ├── base.py             # abstract LLM interface
│       ├── groq.py             # Groq implementation
│       └── gemini.py           # Gemini implementation
│
└── test-fixtures/
    ├── node-app/               # intentionally outdated Node app for testing loopgrade
    │   ├── package.json
    │   ├── index.js
    │   └── index.test.js
    └── python-app/             # intentionally outdated Python app for testing loopgrade
        ├── requirements.txt
        ├── main.py
        └── test_main.py
```

---

## Further Reading

- [How Loop Engineering works](docs/loop_engineering.md) — the architectural pattern loopgrade is built on
- [Configuration deep dive](docs/configuration.md) — all config options with examples
- [Quick reference](docs/quick_references.md) — supported package managers, test fixtures, and FAQ

---

## Contributing

Contributions are welcome — especially:

- Additional package manager support (yarn, pnpm, poetry, cargo)
- Additional LLM providers (OpenAI, Ollama for local models)
- Better conflict resolution strategies
- CI/CD integration (GitHub Actions support)

To get started:

```bash
git clone https://github.com/yourusername/loopgrade
cd loopgrade
pip install -e ".[dev]"

# run tests against the fixtures
cd test-fixtures/node-app && npm install && npm test
cd test-fixtures/python-app && pip install -r requirements.txt && pytest
```

Please open an issue before starting work on a large feature so we can align on the approach.

---
