M7.3: nisse-review's first slice
A new package over nisse-core: it reviews every ready PR in the repositories its account can read, and posts one COMMENT review. - scheduler: each round, open PRs per readable repository (or the configured repositories); an item per PR, ready unless draft or WIP; closed with the PR. One review at a time, oldest first. - reader: the repository at head and base from Gitea archives, unpacked and read in Python (read_file, list_files, search_code), and its issues; bound to the item's repository; no git, no shell. - review: starts from the PR, commits, diff, comments, closed issues, CI; comment drafts a point on any existing line; post_review posts one COMMENT review at the head, inline where Gitea takes it, else as links in the summary. ask_expert; vault and memory (memory/nisse-review). - L8: posting is an intent; recovery asks Gitea for the marked review and never posts twice; with Gitea down, the item waits. - Failures retried, then said on the PR until the next push. - Startup refuses an account that can push to or administer any repo. - nisse-core gitea: readable_repositories, open_pull_requests, diff, commits, archive, issue, search_issues, reviews, post_review; PR fields. - Bring-up: scripts/review-bringup.sh; nisse-review.example.yaml. - Tests: unit over a fake Gitea and scripted model; a live test (NISSE_REVIEW_GITEA_TOKEN) reviews a PR in a fresh test repository. - Docs: Development Plan M7.3, Tuning Guide (tuning.review.*). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
This commit is contained in:
1 parent
fc71d3da75
commit
f59d974a95
24 files changed
+2330
-7
No files matched your search
@@ -600,10 +600,37 @@ waits until two exist to compare. Moved, unchanged in behaviour:
|
||||
milestones, preflight, the go-ahead reader, its fast-path rules, the
|
||||
classifier (until `nisse-ops`), delegation, profiles and projects.
|
||||
|
||||
**M7.3 `nisse-review`'s first slice.** *Needs discussion.* The duty and a work item
|
||||
per ready PR (R1), read-only tools bound to the item's repository (R3), a first
|
||||
review posted on the PR; bring-up on this box, and an end-to-end test against a
|
||||
PR in a test repository.
|
||||
**M7.3 `nisse-review`'s first slice.** *Done.* The `nisse-review` package, over
|
||||
`nisse-core`:
|
||||
|
||||
- **Duty and items (R1):** each round, the open PRs in every repository its
|
||||
account can read (or the configured `repositories`); a work item per PR,
|
||||
ready unless a draft or titled WIP; closed when the PR merges or closes.
|
||||
Every open PR is reviewed, those open when it starts included (operator).
|
||||
- **Reading (R3):** the repository at the PR's head and base, from Gitea's
|
||||
archives, unpacked into a scratch folder and read in Python (`read_file`,
|
||||
`list_files`, `search_code`), and its issues (`read_issue`,
|
||||
`list_issues`): no git, no shell, bound to the item's repository.
|
||||
- **A review:** starts from the PR, its commits, diff, comments, the issues it
|
||||
closes and CI; `comment` drafts a point on any line of any file (checked to
|
||||
exist), `post_review` posts one COMMENT review at the head. Gitea takes
|
||||
comments on the diff inline; one it refuses off the diff goes into the
|
||||
summary as a link to that line (operator: comment on any line).
|
||||
`ask_expert`, and the vault and memory (`memory/nisse-review`, notes per
|
||||
repository).
|
||||
- **Durability (L8):** posting is an intent; after a crash, Gitea is asked
|
||||
whether the review (marked with its head) was posted, and nothing is posted
|
||||
twice; with Gitea down, the item waits.
|
||||
- **Failures:** a failed run is tried again; after `tuning.review.attempts`, it
|
||||
says so on the PR and waits for the next push.
|
||||
- **Access:** startup refuses an account that can push to, or administer, any
|
||||
repository it reads. The token needs `read:user`, `write:issue` and
|
||||
`write:repository` scopes; the account's read access is the limit.
|
||||
- **Bring-up:** `scripts/review-bringup.sh`, a transient systemd unit from the
|
||||
exported code; config and secrets in `/root/nisse-review`.
|
||||
- **Tests:** unit tests over a fake Gitea and a scripted model; a live test
|
||||
(`test_review_live.py`, `NISSE_REVIEW_GITEA_TOKEN`) has the local model
|
||||
review a PR in a fresh test repository.
|
||||
|
||||
**M7.4 `nisse-dev` answers a peer.** *Pre-approved.* Peer comments labelled as a
|
||||
peer's, answered point by point with a change or a reason (D5, R4).
|
||||
|
||||
@@ -597,3 +597,44 @@ work goes on: SSH comes up before a VM has finished booting.
|
||||
services, and fails in confusing ways.
|
||||
- **Too high:** work waits after the VM is ready.
|
||||
- **Deciding:** how long the template takes from SSH answering to fully up.
|
||||
|
||||
## nisse-review's knobs
|
||||
|
||||
`nisse-review` (Part R) has its own configuration (`nisse-review.example.yaml`).
|
||||
`llm.*`, `tuning.expert.consult_budget` and `tuning.context` mean what they
|
||||
mean for `nisse-dev`, above.
|
||||
|
||||
### `tuning.review.poll_s` — default 60
|
||||
|
||||
How often Gitea is asked for PRs that are ready, when nothing is waiting for a
|
||||
review. Each round lists every readable repository's open PRs: a few API calls
|
||||
per repository.
|
||||
|
||||
- **Too low:** load on Gitea for nothing; reviews don't start much sooner.
|
||||
- **Too high:** a PR waits that long for its review to start.
|
||||
|
||||
### `tuning.review.max_turns` — default 40
|
||||
|
||||
A review run's turn cap. Reading files, searching and drafting comments each
|
||||
take a turn; a review that hits the cap posts nothing and counts as a failed
|
||||
try.
|
||||
|
||||
- **Too low:** large PRs fail to be reviewed.
|
||||
- **Too high:** a reviewer that wanders spends long on one PR.
|
||||
- **Deciding:** look at how many turns real reviews take (the transcript) and
|
||||
leave headroom.
|
||||
|
||||
### `tuning.review.diff_chars` — default 60000
|
||||
|
||||
How much of the PR's diff goes into the review's starting context; the rest it
|
||||
reads file by file.
|
||||
|
||||
- **Too low:** the reviewer reads files it could have seen in the diff.
|
||||
- **Too high:** a large diff fills the window before the review starts.
|
||||
- **Deciding:** a fraction of the reviewer's context window (about four
|
||||
characters a token).
|
||||
|
||||
### `tuning.review.attempts` — default 2
|
||||
|
||||
Failed review runs on one PR, at one head, before the reviewer says on the PR
|
||||
that it couldn't review it, and stops trying until the next push.
|
||||
Reference in new issue
Block a user