Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/added-17975-review-perspectives-source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **`review.perspectives_source` is documented.** `src/docs/review-swarm.md` now describes linking the review perspective set to a `kind: ReviewPerspectives` file in a GitHub repo (names and focus text only; `combined_perspectives`, `plan_match` and `max_perspectives_per_pr` stay operator-owned), the source-wins/inline-fallback rule, the last-known-good fallback order with a warning on a malformed document, the shared seed-only `github_prompt_allowlist` trust gate, and the read-only Review Gate display. `hive.yaml.example` gains a commented `perspectives_source:` block ([#17975](https://github.com/hivecommons/hive/issues/17975), [#17990](https://github.com/hivecommons/hive/issues/17990)).
2 changes: 2 additions & 0 deletions src/docs/agent-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,8 @@ This is the property operators most need to understand before enabling the featu

An empty allowlist denies every repo even with `allow_github_prompt: true` β€” the allowlist is required, not merely advisory.

`review.perspectives_source` (the live-linked review perspective set; see [review-swarm.md](review-swarm.md#live-linked-perspectives-reviewperspectives_source)) uses the same seed-only gate: the resolver is allowed to read a repo only when `GitHubPromptAllowed` permits it, it resolves at the same resolve points (startup and every reload), and it follows the same fallback shape as `Resolve` above (last-known-good, then the inline config).

### Fetch failures never blank an agent

`Resolve` (`defsrc.go:283`) never propagates an error to the caller: a reload must proceed even when GitHub is unreachable. On any failure it falls back, in order:
Expand Down
32 changes: 32 additions & 0 deletions src/docs/review-swarm.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ review:
- `perspective_prompts` overrides the focus line for a built-in, or defines a hive-specific perspective entirely (custom names: lowercase letters, digits, single dashes, ≀ 40 chars). A blank entry means the built-in text.
- `combined_perspectives` reviews every enabled perspective in **one** agent session that leaves **one** review comment, with findings grouped under the perspective they belong to. Off, each perspective is its own session and its own comment, and `max_perspectives_per_pr` caps how many a PR receives. Combined mode ignores that cap: it exists to bound comments, and a combined review is always exactly one. The reviewer still emits one verdict per perspective β€” as a JSON array in the verdict file β€” so any single perspective can still hold a PR for a human.

### Live-linked perspectives (`review.perspectives_source`)

`review.perspectives_source` links the perspective set to a file in a GitHub repo, so maintainers add, remove and re-describe perspectives through ordinary PRs instead of a hive config edit (hivecommons/hive#17975). It has the same shape as an agent's `definition_source` (`owner`, `repo`, `path`, optional `ref` that defaults to the repo's default branch; a source missing `owner`, `repo` or `path` counts as unset):

```yaml
review:
combined_perspectives: true # stays operator-owned
perspectives_source:
owner: my-org
repo: my-repo
path: .hive/review-perspectives.yaml
ref: main # optional
```

```yaml
# .hive/review-perspectives.yaml
kind: ReviewPerspectives
perspectives:
- name: correctness # built-in; no focus = built-in text
- name: security
- name: my-constraints # hive-defined; focus is required
focus: "Head size a multiple of 64; fp16 only."
```

- **Names and focus only.** The file holds the perspective names, in dispatch order, and each one's optional focus text, validated exactly like inline `perspectives` / `perspective_prompts` (built-in names may omit `focus`; custom names need it; duplicates, an empty list, a wrong `kind` or a document over 512 KiB are rejected). `combined_perspectives`, `plan_match` and `max_perspectives_per_pr` are cost and dispatch settings and stay operator-owned in the hive config.
- **The source wins; inline is the fallback.** While the source resolves, its set replaces inline `review.perspectives` and `review.perspective_prompts` everywhere the effective set is read (`ReviewConfig.EffectivePerspectives`). Inline values stay in the config and apply whenever nothing resolves.
- **Fallback order.** A fetch that has no GitHub client or fails, and a document that is malformed, each keep the last-known-good document for that source. With none cached, the inline set applies, and if that is empty too, the built-ins. A source whose repo is not on the allowlist is ignored outright (logged, nothing fetched or cached) and the inline set applies. A malformed document keeps the last-known-good set and records a warning rather than quietly dropping to the five built-ins. Only a document that parsed cleanly is remembered, so the cache never holds a corrupt set. A fetch is bounded to 8 seconds.
- **When it resolves.** Resolution happens at startup, before the first relay install, and again on every config reload. Each time the relay's perspective set is reinstalled, so a verdict naming a removed perspective is refused and an added one is accepted without a restart. Heads waiting on a removed perspective settle rather than stay stuck (#14905). A dashboard edit of the review config keeps the linked set.
- **Same trust gate as `definition_source`.** The source repo must be on the seed-only `variables.security.github_prompt_allowlist`; see [agent-configuration.md](agent-configuration.md#the-trust-boundary-allowlisted-repos-are-seed-only).
- **Dashboard.** Governor β†’ Features β†’ Review Gate β†’ Perspectives shows the linked set (not the inline fallback), a "Linked to owner/repo/path@ref" line, and the resolver's status and any warning. The perspective checkboxes and focus text are read-only and "Add perspective" is hidden, and `PUT /api/config/review` answers 409 for `perspectives` / `perspective_prompts` edits that the next resolve would replace. `combined_perspectives`, `plan_match` and `max_perspectives_per_pr` stay editable.

### Combined perspectives: recommended, opt-in

**Turn `combined_perspectives: true` on** (Governor β†’ Features β†’ Review Gate, or the config above) unless you have a reason not to. It is the single largest review-swarm token saving available (hivecommons/hive#12126):
Expand Down Expand Up @@ -181,6 +212,7 @@ review:
fan_out: true
max_parallel_reviews: 5
reviewer_agents: [reviewer-a, reviewer-b] # optional; otherwise agents with review role/keywords are selected
# perspectives_source: {owner: my-org, repo: my-repo, path: .hive/review-perspectives.yaml} # optional; live-link the perspective set, see "Live-linked perspectives"
fixer_agent: scanner # optional; defaults to the PR lane, then scanner
fixer_fallback_agents: [] # opt-in ordered fallback lanes, e.g. [fixer, scanner-2]
fixer_fallback_after_undeliverable: 3 # 0 defaults to 3 only when fallbacks are configured
Expand Down
9 changes: 9 additions & 0 deletions src/hive.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,15 @@ governor:
# combined_perspectives: true # RECOMMENDED (#12126): one session + one comment covering every
# # perspective; shared review boilerplate is sent once instead of once
# # per perspective. Verdicts stay per-perspective. Default false.
# perspectives_source: # optional; live-link the perspective names + focus text to a
# owner: my-org # kind: ReviewPerspectives file in GitHub (#17975). When it resolves it
# repo: my-repo # wins over perspectives/perspective_prompts, which stay the fallback.
# path: .hive/review-perspectives.yaml
# ref: main # optional; default branch otherwise
# # The repo must be on variables.security.github_prompt_allowlist (seed-only).
# # File: "kind: ReviewPerspectives" + "perspectives: [{name, focus}]". Names and
# # focus only; combined_perspectives, plan_match and max_perspectives_per_pr stay
# # here. Format: src/docs/review-swarm.md, "Live-linked perspectives".
# fixer_agent: "" # optional override; defaults to the PR lane, then scanner
# fixer_fallback_agents: [] # opt-in ordered repair lanes, e.g. [fixer, scanner-2]
# fixer_fallback_after_undeliverable: 3 # consecutive refusals before rerouting;
Expand Down
Loading