The bot only ever saw pull requests, so a collaborator with write access who pushes straight to master was invisible: 18 of the last 50 commits on ten31-brand's master arrived that way, unreviewed and unannounced. Opt-in per repo (watch_pushes + [gitea] my_emails). Each poll cycle it pages commits newer than a stored cursor across every branch except ones with an open PR, keeps the commits whose git email isn't mine, posts a notice naming author, branch, commits and files, records them, and only then runs a claude -p assessment threaded under it. Identity comes from the git email because these commits aren't linked to Gitea accounts. The notice is deterministic Gitea data and the "outside the expected area" flag is computed from globs, so the thing you actually need never depends on a model call. Recording before the assessment is what stops a crash in those minutes from reposting the whole notice. Both prompts now put every attacker-authored field — titles, commit subjects, filenames, the diff — inside a nonce-tagged fence, so a forged terminator can't reach the instruction region. Folds in the ROADMAP item to bound two unbounded awaits and exit if the poll task dies, and adds the repo's first test: the watch policy against a real-shaped Gitea fixture, with 17 mutations confirmed to fail it.
30 lines
1.8 KiB
Markdown
30 lines
1.8 KiB
Markdown
# gitea-review-bot
|
|
|
|
A thin Matrix bot that watches a **Gitea** repo from a Matrix room: it reviews and merges pull
|
|
requests, and — opt-in — tells you when someone else pushes commits, with an assessment of what they
|
|
did. One review room per repo. Separate from `matrix-bridge` (which runs interactive Claude Code
|
|
sessions).
|
|
|
|
## How it works
|
|
1. Create a Matrix room named like a repo and invite the bot. It auto-joins and maps the room to
|
|
`<owner>/<repo>` (and `~/Projects/<repo>` on the Mac), then posts an onboarding message.
|
|
2. It polls that repo's open PRs and posts each as a **thread**: a headless `claude -p` review (with
|
|
an optional subagent panel) run on the Mac over SSH.
|
|
3. In the thread: `merge` (then `yes`) or `reject`. A merge auto-deploys (if enabled) and then
|
|
redacts the thread, so the room shows only open PRs; if the deploy fails, the thread still
|
|
clears and a standalone "deploy manually" warning stays in the room. `clear` redacts an
|
|
orphaned thread without touching the PR.
|
|
4. Opt-in per repo, it also watches commits pushed by anyone but you (`watch_pushes` +
|
|
`[gitea] my_emails`): a notice naming the author, branch, commits and files lands immediately,
|
|
and a `claude -p` assessment follows as a threaded reply. `expected_paths` marks where that
|
|
person's changes are expected; anything outside it is flagged in the notice.
|
|
|
|
Pick which review agents run per room in chat: `agents +reviewer +security -adjudicator`.
|
|
|
|
## Run (on the Spark)
|
|
1. Copy `config.example.toml` → `config.toml` and `.env.example` → `.env`; fill them in (Matrix
|
|
creds, `GITEA_TOKEN`, the `[mac]` SSH alias + reused matrix-bridge wrapper paths, `[gitea]`).
|
|
2. `docker compose up -d --build`. Logs: `docker compose logs -f`.
|
|
|
|
See `AGENTS.md` for the full design, placement, and decisions.
|