{"id":50465491,"url":"https://github.com/johnramsden/lp-triage","last_synced_at":"2026-06-01T07:03:33.404Z","repository":{"id":358598726,"uuid":"1204339246","full_name":"johnramsden/lp-triage","owner":"johnramsden","description":"Launchpad triaging scripts","archived":false,"fork":false,"pushed_at":"2026-05-18T04:56:46.000Z","size":194,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T06:50:40.112Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/johnramsden.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-07T23:21:03.000Z","updated_at":"2026-05-18T04:56:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/johnramsden/lp-triage","commit_stats":null,"previous_names":["johnramsden/lp-triage"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/johnramsden/lp-triage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnramsden%2Flp-triage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnramsden%2Flp-triage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnramsden%2Flp-triage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnramsden%2Flp-triage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johnramsden","download_url":"https://codeload.github.com/johnramsden/lp-triage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnramsden%2Flp-triage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33763666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-01T07:03:32.609Z","updated_at":"2026-06-01T07:03:33.397Z","avatar_url":"https://github.com/johnramsden.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lp-triage\n\nAI-powered Launchpad bug triage for Ceph charms. Fetches active bugs from\nLaunchpad, runs an agentic classification loop against the charm source\nrepository, and optionally posts the result as a comment on the bug.\n\n## Requirements\n\n- Python 3.12+\n- [uv](https://docs.astral.sh/uv/)\n- An [OpenRouter](https://openrouter.ai) API key (or a Gemini API key)\n\n## Installation\n\n```bash\nuv sync\n```\n\nInstall Chromium once for Playwright UI tests:\n\n```bash\nuv run playwright install chromium\n```\n\n## Configuration\n\nAll configuration lives in a single file: `~/.config/lp-triage/config.toml`\n\nThis includes both personal settings (API keys, provider, model) and the list\nof Launchpad projects to triage.\n\nMinimal config:\n\n```toml\n# ~/.config/lp-triage/config.toml\n[auth]\nopenrouter_api_key = \"sk-or-...\"\n\n[[projects]]\nlp_project = \"charm-ceph-mon\"\nurl        = \"https://github.com/canonical/ceph-charms\"\nbranch     = \"main\"\nsubdir     = \"ceph-mon\"      # optional — omit to scope to the whole repo\n```\n\nOr set API keys via environment variables:\n\n```bash\nexport OPENROUTER_API_KEY=\"sk-or-...\"\nexport GEMINI_API_KEY=\"...\"\n```\n\nMultiple projects can share the same repository URL; the repo is cloned once.\n\n### Full config defaults\n\n```toml\n[defaults]\nprovider      = \"openrouter\"   # or \"gemini\"\nconcurrency   = 4              # parallel bugs per project\nmax_turns     = 10             # agent loop iterations per bug\nbug_list_ttl  = 3600           # LP bug list cache TTL in seconds\ncache_dir     = \"~/.cache/lp-triage\"\nlp_instance   = \"production\"   # LP instance: production, qastaging, staging\n\n[auth]\nlp_credentials_file = \"~/.config/lp-triage/lp-credentials\"  # set by OAuth flow\n\n[openrouter]\nmodel    = \"openrouter/auto\"\nbase_url = \"https://openrouter.ai/api/v1\"\n\n[gemini]\nmodel = \"gemini-2.0-flash\"\n```\n\n## CLI usage\n\n```bash\n# Classify bugs, human-readable output\nuv run lp-triage run --human\n\n# Specific projects, cap at 5 bugs each\nuv run lp-triage run --projects charm-ceph-mon charm-ceph-osd --limit 5 --human\n\n# Generate comments without posting (dry run)\nuv run lp-triage run --post-comment --dry-run --human\n\n# Post comments for real (capped at 20 by default)\nuv run lp-triage run --post-comment --human\n\n# Use Gemini instead of OpenRouter\nuv run lp-triage run --provider gemini --human\n\n# Show merged config (secrets masked)\nuv run lp-triage config\n```\n\nOutput is NDJSON by default; `--human` prints readable lines. Each run writes\na timestamped NDJSON log (`run-\u003cts\u003e.ndjson`) and a plain-text summary\n(`run-\u003cts\u003e-summary.txt`) to the current working directory.\n\n### All CLI flags\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--projects` | all | LP project names to triage |\n| `--limit N` | all | Max bugs per project |\n| `--provider` | from config | `openrouter` or `gemini` |\n| `--model` | from config | Override model for this run |\n| `--concurrency N` | 4 | Parallel bugs within a project |\n| `--max-turns N` | 10 | Agent loop iterations per bug |\n| `--refresh` | off | Bypass LP bug list cache |\n| `--post-comment` | off | Post AI comment to each LP bug |\n| `--dry-run` | off | Run full flow but skip LP writes |\n| `--max-posts N` | 20 | Cap on comments posted per run |\n| `--human` | off | Human-readable output |\n| `--debug` | off | Include tool-call events in output |\n\n## Web UI\n\n```bash\nuv run lp-triage serve          # http://localhost:8080\nuv run lp-triage serve --open   # opens browser automatically\nuv run lp-triage serve --port 9090\n```\n\n### Modes\n\n**Auto** — runs the full triage and posts comments automatically when evidence\nis found (subject to dry-run and max-posts limits).\n\n**Review** — each classification is queued for human approval. Edit the draft\ncomment in-place if needed, then click **Approve \u0026 post** or **Skip**.\n\n**Allow reposting** — by default bugs that already have an lp-triage comment\nare skipped. Enable this checkbox to include them; they appear in the review\nqueue with a warning so you can decide whether a second post makes sense.\nThis option is web-UI-only; the CLI never reposts.\n\n### Connecting Launchpad (for posting comments)\n\n1. Open **Configuration → Connect Launchpad**.\n2. Authorize `lp-triage` in the new tab that opens.\n3. Return to the app and click **Complete authorization**.\n\nCredentials are saved to `~/.config/lp-triage/lp-credentials` in launchpadlib\nformat and reused on subsequent runs.\n\n## Testing\n\n```bash\nuv run pytest                        # all tests\nuv run pytest tests/unit             # unit tests only\nuv run pytest tests/integration      # integration tests (runs a real FastAPI server)\nuv run pytest tests/ui               # Playwright browser tests (requires Chromium)\n```\n\nTests must pass before any change is considered complete. See\n[`architecture/`](architecture/) for the design rationale behind each module.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnramsden%2Flp-triage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohnramsden%2Flp-triage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnramsden%2Flp-triage/lists"}