Metadata-Version: 2.4
Name: caretaker-github
Version: 0.28.4
Summary: Autonomous GitHub repository maintenance powered by Copilot
Project-URL: Homepage, https://github.com/ianlintner/caretaker
Project-URL: Documentation, https://ianlintner.github.io/caretaker/
Project-URL: Repository, https://github.com/ianlintner/caretaker
Project-URL: Issues, https://github.com/ianlintner/caretaker/issues
Author: Caretaker Contributors
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.14
Requires-Dist: anthropic<1,>=0.40
Requires-Dist: click<9,>=8
Requires-Dist: httpx<1,>=0.27
Requires-Dist: packaging<25,>=24
Requires-Dist: prometheus-client<1,>=0.20
Requires-Dist: prometheus-fastapi-instrumentator<8,>=7.0
Requires-Dist: pydantic<3,>=2
Requires-Dist: pyyaml<7,>=6
Provides-Extra: admin
Requires-Dist: authlib<2,>=1.3; extra == 'admin'
Requires-Dist: fastapi<1,>=0.100; extra == 'admin'
Requires-Dist: httpx<1,>=0.27; extra == 'admin'
Requires-Dist: itsdangerous<3,>=2.1; extra == 'admin'
Requires-Dist: neo4j<6,>=5.0; extra == 'admin'
Requires-Dist: redis[asyncio]<6,>=5; extra == 'admin'
Requires-Dist: uvicorn<1,>=0.23; extra == 'admin'
Provides-Extra: backend
Requires-Dist: fastapi<1,>=0.100; extra == 'backend'
Requires-Dist: motor<4,>=3.3; extra == 'backend'
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'backend'
Requires-Dist: redis[asyncio]<6,>=5; extra == 'backend'
Requires-Dist: uvicorn<1,>=0.23; extra == 'backend'
Provides-Extra: dev
Requires-Dist: fastapi<1,>=0.100; extra == 'dev'
Requires-Dist: httpx<1,>=0.27; extra == 'dev'
Requires-Dist: motor<4,>=3.3; extra == 'dev'
Requires-Dist: mypy<2,>=1.13; extra == 'dev'
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'dev'
Requires-Dist: pytest-asyncio<2,>=1; extra == 'dev'
Requires-Dist: pytest-cov<6,>=5; extra == 'dev'
Requires-Dist: pytest<10,>=9.0.3; extra == 'dev'
Requires-Dist: redis[asyncio]<6,>=5; extra == 'dev'
Requires-Dist: respx<1,>=0.22; extra == 'dev'
Requires-Dist: ruff<1,>=0.7; extra == 'dev'
Requires-Dist: types-pyyaml<7,>=6; extra == 'dev'
Requires-Dist: types-redis<5,>=4.6; extra == 'dev'
Requires-Dist: uvicorn<1,>=0.23; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material<10,>=9.5; extra == 'docs'
Requires-Dist: mkdocs<2,>=1.6; extra == 'docs'
Provides-Extra: eval
Requires-Dist: braintrust<1,>=0.0.170; extra == 'eval'
Provides-Extra: github-app
Requires-Dist: fastapi<1,>=0.100; extra == 'github-app'
Requires-Dist: pyjwt[crypto]<3,>=2.8; extra == 'github-app'
Requires-Dist: uvicorn<1,>=0.23; extra == 'github-app'
Provides-Extra: k8s-worker
Requires-Dist: kubernetes<34,>=30; extra == 'k8s-worker'
Provides-Extra: llm-multi
Requires-Dist: aiohttp>=3.13.5; extra == 'llm-multi'
Requires-Dist: litellm<2,>=1.83.7; extra == 'llm-multi'
Provides-Extra: otel
Requires-Dist: opentelemetry-api<2,>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-exporter-otlp<2,>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-instrumentation-fastapi<1,>=0.46; extra == 'otel'
Requires-Dist: opentelemetry-instrumentation-httpx<1,>=0.46; extra == 'otel'
Requires-Dist: opentelemetry-instrumentation-redis<1,>=0.46; extra == 'otel'
Requires-Dist: opentelemetry-sdk<2,>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-semantic-conventions<1,>=0.46; extra == 'otel'
Description-Content-Type: text/markdown

# Caretaker

Autonomous GitHub repository management powered by Copilot and github app.

<img width="100" alt="Caretaker Avatar" src="https://github.com/user-attachments/assets/fb236484-2b83-41c6-b836-ec6f2d378b46" />

Documentation: https://ianlintner.github.io/caretaker/

**One issue. No CLI. No tooling.** Paste a setup issue into your repo, assign it to `@copilot`, walk away. Your repo is now autonomously maintained.

---

## How It Works

1. **You** paste a setup issue into your repo and assign it to `@copilot`
2. **Copilot** reads our [SETUP_AGENT.md](setup-templates/SETUP_AGENT.md), analyzes your repo, and opens a PR with everything configured
3. **You** merge the PR
4. **The orchestrator** runs daily via GitHub Actions, managing PRs, issues, and upgrades

The orchestrator uses Copilot as its execution engine — it observes your repo state, decides what needs to happen, and delegates code changes to Copilot via structured comments.

---

## Setup

### 1. Create a new issue in your repo:

> **Tip:** Visit the [Getting Started docs](https://ianlintner.github.io/caretaker/getting-started/) and use the **copy** button on the code block below to copy the issue template in one click.

```markdown
## Setup Caretaker

@copilot Please set up the caretaker system for this repository.

### Instructions

1. Read the setup guide at:
   https://github.com/ianlintner/caretaker/blob/main/setup-templates/SETUP_AGENT.md

2. Follow the instructions in that guide exactly.

3. After creating all files, open a single PR with the changes.
   Title: "chore: setup caretaker"

### Context

This repo uses the caretaker system for automated repo management.
See: https://github.com/ianlintner/caretaker
```

### 2. Assign the issue to `@copilot`

### 3. Review and merge the PR that Copilot opens

### 4. Add `COPILOT_PAT` from a write-capable user for Copilot hand-offs, and `ANTHROPIC_API_KEY` for enhanced AI features

`COPILOT_PAT` should be a fine-grained PAT that belongs to a real user or machine user with write access to the repository.
Caretaker uses that token for:

- API-based assignment of issues to GitHub Copilot
- PR comments that `@copilot` must see as coming from a write-capable identity rather than `github-actions[bot]`

---

## What Gets Installed

After setup, your repo has:

```
.github/
  copilot-instructions.md         ← Copilot project memory (appended)
  agents/
    maintainer-pr.md              ← PR agent persona
    maintainer-issue.md           ← Issue agent persona
    maintainer-upgrade.md         ← Upgrade agent persona
  maintainer/
    config.yml                    ← Repo-specific settings
    .version                      ← Pinned version
```

No Python. No Node. No vendored code. **No GitHub Actions workflow either** — all
execution happens server-side, driven by App webhooks. Just config and Copilot
instructions.

---

## Features

### Core Agents

#### PR Agent
- Monitors all open PRs in real-time
- Detects and triages CI failures (test, lint, build, type errors)
- Requests fixes from Copilot via structured comments
- Retry loop with escalation after max attempts
- Auto-merge for Copilot, Dependabot, and human PRs (configurable)
- Handles flaky test detection and CI re-runs
- Review state analysis and auto-approval (configurable)

#### Issue Agent
- Triages incoming issues (bug, feature, question, duplicate, stale)
- Dispatches implementable issues to Copilot
- Tracks issue → PR → merge lifecycle
- Auto-closes answered questions and stale issues (configurable)
- Escalates complex issues to repo owners

#### DevOps Agent
- Monitors default-branch CI failures
- Automatically creates fix issues for build/test failures
- Deduplicates similar issues with cooldown periods
- Assigns work to Copilot for resolution

#### Self-Heal Agent
- Detects backend agent failures during a run
- Creates self-diagnosis issues
- Reports bugs to upstream caretaker repository (configurable)
- Ensures the system can maintain itself

#### Security Agent
- Triages Dependabot alerts
- Monitors code scanning findings
- Tracks secret scanning alerts
- Filters by severity thresholds
- Creates remediation issues with context

#### Dependency Agent
- Reviews Dependabot PRs
- Auto-merges patch and minor updates (configurable)
- Posts dependency update digests
- Smart merge strategies by update type

#### Docs Agent
- Reconciles merged PRs into changelog updates
- Maintains documentation freshness
- Configurable lookback period
- Optional README updates

#### Charlie Agent
- Cleans up duplicate caretaker-managed issues and PRs
- Closes abandoned work after 14-day default window
- Prevents operational clutter accumulation
- Exempt label support for critical work

#### Stale Agent
- Warns and closes stale issues and PRs (60+ days default)
- Deletes merged branches automatically
- Configurable stale thresholds
- Exempt labels for pinned or security work

#### Escalation Agent
- Creates human escalation digest issues
- Aggregates work requiring maintainer attention
- Configurable targets and notification
- Tracks escalation age and priority

#### Upgrade Agent
- Detects new caretaker releases
- Creates upgrade issues for Copilot execution
- Supports multiple strategies: auto-minor, auto-patch, latest, pinned
- Handles breaking vs. non-breaking upgrades
- Version pinning via `.version` file
- Preview channel support

### Advanced Features

#### Goal Engine (Experimental)
- Quantitative goal-based agent dispatch
- Measures repository health across dimensions:
  - CI health (green builds on main and PRs)
  - PR lifecycle velocity
  - Security posture
  - Self-health monitoring
- Scores each goal from 0.0 (unmet) to 1.0 (satisfied)
- Prioritizes agents based on goal impact
- Detects divergence and critical states
- Tracks goal history for trend analysis

#### Memory Store
- Disk-backed SQLite storage for agent memory
- Persistent deduplication across runs
- Namespaced memory for different agent concerns
- Automatic snapshot generation for auditing
- Bounded storage with configurable limits

### Optional: Claude Integration

Add `ANTHROPIC_API_KEY` to unlock enhanced AI features:

- **CI log analysis** — better at parsing long, noisy logs
- **Architectural review** — understands complex code review comments
- **Issue decomposition** — breaks down multi-faceted bugs
- **Upgrade impact analysis** — assesses breaking change risk

### Optional: OpenRouter Integration

Set `OPENROUTER_API_KEY` (or its accepted alias `OPEN_ROUTER_API_KEY`)
and `provider: openrouter` in
`.github/maintainer/config.yml` to route LLM calls through
[OpenRouter](https://openrouter.ai), which gives you:

- **300+ models behind one key** — DeepSeek R1, Gemini, Llama, Qwen,
  GLM, plus all the proprietary frontier models.
- **Per-feature model routing** — pin different caretaker features to
  different best-fit models via `feature_models`.
- **Web-grounded analysis** — append `:online` to a model string to add
  a web search step before the completion. Caretaker ships this as the
  default for `upgrade_impact_analysis`, `migration_analysis`, and
  `migration_plan` so release-note and breaking-change context comes
  from current sources rather than stale model knowledge.

Sample config:

```yaml
llm:
  provider: openrouter
  default_model: openrouter/anthropic/claude-sonnet-4.6
  feature_models:
    ci_log_analysis:
      model: openrouter/deepseek/deepseek-r1
    principal_architecture_review:
      model: openrouter/anthropic/claude-opus-4.6
```

**Cost note:** `:online` adds OpenRouter's web-search step
(~$4 per 1k searches) on top of the model call. The
`caretaker.llm.online=true` OTel span attribute lets you break out
web-grounded spend in cost dashboards.

When `provider: openrouter` is set, every model string must begin
with `openrouter/`. Caretaker rejects bare model names at
config-load to prevent the silent bypass to Anthropic-direct that
LiteLLM otherwise performs.

---

## What's new

### Fleet registry (opt-in)

Each consumer repo's successful `caretaker run` can POST a small
heartbeat to a central caretaker backend so an operator sees every
managed repository in one dashboard — without running an org-wide
GitHub crawl.

Enable in `.github/maintainer/config.yml`:

```yaml
fleet_registry:
  enabled: true
  endpoint: https://<your-caretaker-backend>/api/fleet/heartbeat
```

See [docs/fleet-registry.md](docs/fleet-registry.md) for architecture,
payload shape, and HMAC-signed delivery.

### Custom coding agent

Small tasks (lint fixes, trivial test failures, review comments) no
longer have to go to `copilot-swe-agent[bot]`. A configurable
executor routes them to caretaker's own Foundry tool-loop or to an
`anthropics/claude-code-action` hand-off, with a size-budget guard
and an explicit escalation path back to Copilot.

Three routing labels let operators steer individual items:

- `agent:custom` — force the custom executor.
- `agent:copilot` — force the legacy path.
- `agent:quarantine` — refuse dispatch (for hostile or confusing issues).

On AKS deployments, the MCP backend exposes
`POST /api/admin/agent-tasks` which spawns a short-lived
`batch/v1 Job` per dispatch. See
[docs/custom-coding-agent-plan.md](docs/custom-coding-agent-plan.md)
for the full design, phased rollout, size budget, and security model;
[docs/custom-coding-agent-e2e.md](docs/custom-coding-agent-e2e.md)
for the operator runbook.

---

## Configuration

See [setup-templates/templates/config-default.yml](setup-templates/templates/config-default.yml) for the full config schema.

Key settings:

```yaml
pr_agent:
  auto_merge:
    copilot_prs: true # Auto-merge Copilot PRs
    dependabot_prs: true # Auto-merge dependency updates
  copilot:
    max_retries: 2 # Fix attempts before escalation

issue_agent:
  auto_assign_bugs: true # Auto-assign simple bugs to Copilot
  auto_assign_features: false

devops_agent:
  target_branch: main # Monitor default branch CI
  max_issues_per_run: 3 # Prevent issue spam
  dedup_open_issues: true

security_agent:
  min_severity: medium # Filter by severity
  include_dependabot: true
  include_code_scanning: true
  include_secret_scanning: true

dependency_agent:
  auto_merge_patch: true
  auto_merge_minor: true
  post_digest: true

charlie_agent:
  stale_days: 14 # Short janitorial window for caretaker-managed work
  close_duplicate_issues: true
  close_duplicate_prs: true

stale_agent:
  stale_days: 60 # General stale threshold
  close_after: 14
  delete_merged_branches: true

upgrade_agent:
  strategy: auto-minor # auto-minor | auto-patch | latest | pinned
  channel: stable # stable | preview

goal_engine:
  enabled: false # Experimental: goal-driven dispatch
  goal_driven_dispatch: false # Reorder agents by goal impact
  divergence_threshold: 3 # Runs before triggering alerts

memory_store:
  enabled: true # Persistent agent memory
  db_path: .caretaker-memory.db
  max_entries_per_namespace: 1000
```

---

## Architecture

```
Orchestrator (Python, runs in GitHub Actions)
  │
  ├── Reads config.yml
  ├── Reads repo state (open PRs, issues, CI status)
  ├── Decides what needs to happen
  │
  ├── For code changes → creates/updates issues → assigns to @copilot
  ├── For PR fixes → posts structured comments as the `COPILOT_PAT` identity → @mentions copilot
  └── For escalation → labels + tags repo owner
```

The orchestrator **never writes code**. It manages Copilot, which does.

---

## Development

```bash
# Clone and install
git clone https://github.com/ianlintner/caretaker.git
cd caretaker
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Lint
ruff check src/ tests/
ruff format --check src/ tests/

# Type check
mypy src/
```

---

## License

MIT
