feat(review): multi-lens orchestration — 5 parallel opencode subprocesses (security/docs/code-quality/tests/perf)
On by default, opt-out via "reviewers": []. 290 tests pass.
- pilot/opencode_review.py: ReviewerSpec dataclass, default_reviewers(),
parse_reviewers_config(), parse_triage_config(), resolve_reviewers(),
_normalize_lens_finding(), posthash() (matches feedback.py scheme),
_agreement_hash() (severity-free for cross-lens promotion), _tone_strip(),
synthesize() 7-stage (severity_floor → tone-strip → length cap → per-lens
max → per-file cap → dedup by _posthash → cross-lens severity promote →
per-PR cap), run_lenses() (ThreadPoolExecutor pool=4), triage(),
_intersect_with_triage(), _filter_by_skip_if(), run_lenses_review().
run() routes to fan-out when config.reviewers[] present or PRAGENT_REVIEWERS=1.
- pilot/ai_review.py: parse_repo_config learns reviewers[] and triage objects
(id regex /^[a-z0-9][a-z0-9-]{0,31}$/, 8-entry cap, agent_file/model/
severity_floor/max_findings/activation/skip_if_all_changed_paths/hotpath_globs).
review_pr branches to opencode_review.run_lenses_review when configured.
_render_collapsible_usage shows lenses: ... line when present.
- .opencode/agents/{docs,code-quality,triage}.md: 3 new lens subagents.
- .opencode/skills/lens-orchestration/SKILL.md: strict-JSON contract every
lens subagent MUST honor.
- .opencode/agents/pragent.md: slim to coordinator; no more hardcoded
@security/@tests/@perf delegation; loads lens-orchestration skill.
- .opencode/README.md: rewrite 'Add a review lens' recipe for multi-lens.
- pilot/README-webhook.md: new 'Multi-lens pipeline' section (diagram +
default roster + config schema + env vars + cross-lens dedup contract).
- tests: 36 new tests (test_ai_review.py +12 reviewers/triage/usage,
test_opencode_review.py +24 orchestration). posthash golden-vector matches
feedback.py exactly across 5 severity × 2 line cases.
This commit is contained in:
+35
-15
@@ -71,22 +71,42 @@ host-local runs deterministic.
|
||||
|
||||
### Add a review lens (subagent)
|
||||
|
||||
1. Create `.opencode/agents/<name>.md` with `mode: subagent`, `hidden: true`, a
|
||||
`description`, and a read-only `permission` (deny edit/write, allow bash/webfetch,
|
||||
`task: deny` so it can't recurse). The body is its system prompt; end it by
|
||||
requiring the same findings-JSON shape.
|
||||
2. Allow it in the primary's `permission.task` list in `pragent.md`:
|
||||
```yaml
|
||||
task:
|
||||
"*": "deny"
|
||||
"security": "allow"
|
||||
"tests": "allow"
|
||||
"<name>": "allow" # add this
|
||||
```
|
||||
3. Mention in `pragent.md`'s "Delegate on heavy diffs" step when to invoke it.
|
||||
Multi-lens orchestration is now Python-side (`pilot/opencode_review.py`).
|
||||
Each lens is just a `.md` file; the Python side spawns one subprocess per
|
||||
lens in parallel and synthesises the merged findings.
|
||||
|
||||
That's it — the primary can now `@<name>` it via the Task tool. It stays dormant
|
||||
(the primary decides when), so adding it costs nothing for small PRs.
|
||||
1. Create `.opencode/agents/<id>.md` with frontmatter:
|
||||
```yaml
|
||||
---
|
||||
description: One line that names what this lens catches.
|
||||
mode: subagent
|
||||
hidden: true
|
||||
model: headroom/glm-5.2:cloud
|
||||
temperature: 0.1
|
||||
permission:
|
||||
edit: deny
|
||||
write: deny
|
||||
bash: "allow" # or narrow: "<cmd>": "allow"
|
||||
webfetch: allow
|
||||
task: deny
|
||||
---
|
||||
```
|
||||
Body = the system prompt. End it with the **strict JSON contract** in
|
||||
`.opencode/skills/lens-orchestration/SKILL.md` (findings shape, `severity_floor`,
|
||||
no writes outside workdir, prompt-injection reporting). A real lens has
|
||||
target paths + output schema + tool budget + example findings — not just a
|
||||
different system prompt.
|
||||
2. Add one entry to the repo's `.pr-review.json:reviewers[]`:
|
||||
```jsonc
|
||||
{ "id": "<id>", "severity_floor": "low", "max_findings": 8 }
|
||||
```
|
||||
No Python change. No image rebuild. The orchestrator picks it up next run.
|
||||
3. (Optional) Tighter defaults: `activation: "off"` to ship-disabled,
|
||||
`skip_if_all_changed_paths: "docs/**"` to skip when only docs changed,
|
||||
`hotpath_globs: ["**/queries/**"]` to help triage recognise the lens.
|
||||
|
||||
**Built-in lenses** (you can override any of them): `security`, `docs`,
|
||||
`code-quality`, `tests`, `perf`. Set `reviewers: []` to opt out.
|
||||
|
||||
### Add a skill
|
||||
|
||||
|
||||
Reference in New Issue
Block a user