feat: v0.3.0 — per-lens threshold + weighted signals#2
Conversation
Closes the "global scoring rules apply to every lens" limitation. Lenses
can now declare their own `threshold` (top-level) and `signals.weights`
(nested per-signal-type) to tune routing for their specificity.
Added (v0.3.0 optional fields):
- `threshold: int` — per-lens score threshold override; defaults to 2
- `signals.weights: {paths, prompt_keywords, branch_patterns, linear_labels}`
— per-signal-type integer multipliers; defaults to 1 each; 0 disables
Implementation:
- `_resolve_threshold(lens)` / `_resolve_weights(lens)` helpers
- `_score_lens` now computes Σ(raw_count × weight) per signal type
- `_select_lenses` selects on `score(L) >= effective_threshold(L)`
- `validate_lens` rejects non-positive threshold, non-int / negative weight,
unrecognised weight keys
Tests (13 → 20):
- per_lens_threshold_3_blocks_2_signal_fire
- per_lens_threshold_1_fires_on_single_signal
- weighted_keyword_amplifies_single_hit_to_fire
- zero_weight_disables_signal_type
- validate_rejects_negative_threshold
- validate_rejects_unknown_weight_key
- validate_accepts_v030_optional_fields
Backward compatibility:
- All v0.1.0/v0.2.0 lenses (no threshold, no weights) keep identical
scoring (weights default 1 → Σ × 1 = current sum)
- events.jsonl schema unchanged — recorded counts remain raw (unweighted)
- CLI signatures unchanged
- Workspace lenses (_meta + rust-systems) verified: validate clean,
intake fires rust-systems on 3-keyword Rust prompt as before
Docs updated:
- CHANGELOG.md v0.3.0 entry with example
- README.md roadmap (v0.3.0 = trigger strategies; M3-M5 renumbered to v0.4-0.6)
- references/lens-schema.md — Optional fields section with security-review example
- references/selection-algorithm.md — weighted score formula + per-lens threshold notes
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR upgrades the role-x lens trigger strategy to v0.3.0 by introducing optional per-lens Changesv0.3.0 Trigger-Strategy Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Trigger-strategy upgrade. Lenses can now declare:
threshold: int(top-level) — per-lens score threshold override; defaults to 2signals.weights.<type>: int(nested) — per-signal-type multiplier; defaults to 1; `0` disablesCloses the "global scoring rules apply to every lens" limitation from v0.1.0/v0.2.0. Specialist lenses can raise threshold to 3 to avoid false positives; broad lenses can lower to 1; branch-pattern-dominant lenses can weight branch matches 3× and keyword matches 1× to reflect signal specificity.
Example — strict security-review lens
```yaml
name: security-review
threshold: 3
signals:
paths: ["/auth/", "**/credentials*"]
prompt_keywords: ["auth", "secret", "credential", "JWT", "OAuth"]
branch_patterns: ["feat/auth-", "feat/security-"]
linear_labels: ["topic:security"]
weights:
branch_patterns: 3 # branch is a strong signal
prompt_keywords: 1
paths: 1
…
```
Prompt = "rotate the JWT signing key" on branch `feat/auth-rotate` →
Without weights, this would be 1+1+0=2 — below threshold; lens wouldn't fire.
Test plan
Backward compatibility
Lenses without `threshold` or `signals.weights` keep identical v0.2.0 scoring. No migration needed.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation