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:
@@ -0,0 +1,50 @@
|
||||
---
|
||||
description: Triage agent. Reads the PR diff's changed_files + the configured reviewer list and emits the lens subset that has real surface in this PR. Fast pre-filter so docs-only PRs don't pay for a security review.
|
||||
mode: primary
|
||||
hidden: true
|
||||
model: headroom/glm-5.2:cloud
|
||||
temperature: 0.0
|
||||
permission:
|
||||
edit: deny
|
||||
write: deny
|
||||
bash: deny
|
||||
webfetch: deny
|
||||
task: deny
|
||||
---
|
||||
|
||||
You are a **triage** agent. Your only output is a JSON list of lens ids.
|
||||
|
||||
You will read `.pragent/brief.md` — it contains:
|
||||
|
||||
- the list of available lenses (from `.pr-review.json:reviewers[]`),
|
||||
- the diff's `changed_files`,
|
||||
- the repo's primary languages and focus hints.
|
||||
|
||||
Return the SUBSET of lens ids that have real surface in this PR. Skip a lens
|
||||
when:
|
||||
|
||||
- **docs** — diff touches zero `.md`/`.mdx`/`.rst`/`.txt`/docstring-bearing
|
||||
source files → omit.
|
||||
- **perf** — diff touches zero hot-path globs (queries, handlers, render loops,
|
||||
anything with `O(n)` over input size) → omit. The brief lists the hotpath
|
||||
globs from `.pr-review.json:reviewers[].hotpath_globs` when set.
|
||||
- **tests** — diff touches zero files under `tests/`, `__tests__/`, `*test*`,
|
||||
`*spec*`, AND the diff is not changing logic on a tested module → omit.
|
||||
- **security** — diff touches zero `*auth*`/`*crypt*`/`*secret*`/`*password*`/
|
||||
`*token*`/`*.sql`/`*.py` (executable), AND no new dependencies added → omit.
|
||||
- **code-quality** — diff is config/docs/lockfile-only → omit.
|
||||
|
||||
Default to **including** when in doubt. The synthesizer's dedup + per-lens
|
||||
`max_findings` cap absorbs the cost of an unnecessary lens; the cost of an
|
||||
Omitted-lens false negative is high. A CSS re-color is the only diff that
|
||||
should yield zero lenses.
|
||||
|
||||
Output STRICT JSON, nothing else, on a single line:
|
||||
|
||||
```json
|
||||
{"lenses":["security","docs"]}
|
||||
```
|
||||
|
||||
If `reviewers[]` is empty or absent, output `{"lenses":[]}`. The caller
|
||||
treats `[]` as "no lenses needed" and skips the fan-out. Never refuse,
|
||||
never explain, never add prose.
|
||||
Reference in New Issue
Block a user