You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
code-review: make DOMAIN_CRITIC_CAP operator-tunable
The domain-critic cap was a hardcoded 3 with no settings path, and it
drops by (priority asc, reviewer asc). A repo whose critic-gates.json
uses the legacy moduleCritics[] schema gets every entry migrated as
required:False with no priority, so all of them sit at the default 2 and
the tiebreak degenerates to alphabetical by reviewer name. That
deterministically cuts the critic the coverage critic proposed FOR the
diff: on two symphony-alpha cost/metric PRs, logical-metric-reconciliation-auditor
was accepted by consolidate and then dropped, while api-architect,
caching-strategist and database-architect survived on their first letter.
Adds domain_critic_cap to code-review.json (the file that already hosts
bha_unified_threshold_loc and out_of_hunk_confidence_floor), plus an
--domain-critic-cap namespace override and --settings for test isolation
on arbitrate-budget. Precedence mirrors bha_unified_threshold_loc:
flag > settings file > built-in default. 0 is a valid kill switch
(no domain critics; source:"core" reviewers stay exempt); negative and
non-int values fall back to the default rather than crashing the stage.
Raising the cap is the blunt remedy — the precise one is migrating rules
to the canonical coverage[] schema, which supports explicit priority and
required. Both are now documented in README and start.md.
Tests: 9 new (5 loader validation, 4 arbitrate-budget behavior incl.
precedence, the 0 kill switch, and malformed-value fallback). The shared
_run_arbitrate_budget harness now always points --settings at a
test-local path so a code-review.json in the CWD cannot leak into a run.
Full suite 1339 passed / 3 skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|`impact_analyzer` (FEA-1401, on exported-symbol change/deletion) | ✗ | ✗ | ✓ (on signal) |
192
192
193
-
**Standard-mode budget arithmetic.** With PLN-807 Phase 4, `arbitrate-budget` reserves BHA partitions FIRST (from `_max_bha_partitions_by_loc`) and then allocates the remaining budget to critics and best-effort. The total domain-critic count across both required and best-effort buckets is capped uniformly at `DOMAIN_CRITIC_CAP = 3` (by priority asc, reviewer asc) for both standard and deep tiers. Required-bucket critics dropped by the cap emit coverage-gap findings; cap-deferred entries carry `defer_reason: "domain_critic_cap"` in `deferred_for_budget`. PRs with sparse critic-gates rosters see identical fleet to pre-PLN-807.
193
+
**Standard-mode budget arithmetic.** With PLN-807 Phase 4, `arbitrate-budget` reserves BHA partitions FIRST (from `_max_bha_partitions_by_loc`) and then allocates the remaining budget to critics and best-effort. The total domain-critic count across both required and best-effort buckets is capped uniformly at `DOMAIN_CRITIC_CAP` (default 3, operator-tunable via `.closedloop-ai/settings/code-review.json:domain_critic_cap`; by priority asc, reviewer asc) for both standard and deep tiers. Required-bucket critics dropped by the cap emit coverage-gap findings; cap-deferred entries carry `defer_reason: "domain_critic_cap"` in `deferred_for_budget`. PRs with sparse critic-gates rosters see identical fleet to pre-PLN-807.
194
194
195
195
**Tier-mismatch nudge.** Shallow runs emit a single LOW system-scoped finding (`system_marker: "tier_mismatch_nudge"`) when the diff would benefit from a higher tier. Heuristics: diff > 3000 LOC; schema/migration paths (`/migrations/`, `/schemas/`, `/models/`); public API surface (`plugin.json`, `index.ts`, `__init__.py`, etc.).
196
196
@@ -305,11 +305,15 @@ Sensitive-path policy. See `start.md` for the full glob syntax and the three sup
305
305
306
306
### `code-review.json` (PLN-774)
307
307
308
-
Operator-tunable reviewer behavior. Currently exposes the BHA conditional-partitioning threshold; future knobs will land here too.
308
+
Operator-tunable reviewer behavior.
309
309
310
310
| Key | Default | Behavior |
311
311
|---|---|---|
312
312
|`bha_unified_threshold_loc`|`5000`| PRs with total changed LOC at or below this value get a single "unified" BHA partition so cross-region invariants (declaration ↔ enforcement, definition ↔ reference) stay visible to one reviewer's context. PRs above the threshold fall back to the standard bin-pack (`REBALANCE_LOC_BUDGET=1200` LOC per partition). **Setting the value to `0` disables unified mode entirely (always-partition; restores pre-PLN-774 behavior — the regression escape hatch).** Invalid entries (wrong type, negative) silently fall back to the default. |
313
+
|`out_of_hunk_confidence_floor`|`0.80`| P2+ findings whose line falls outside the file's changed range survive validation when `confidence >` this floor. `1.0` is a kill switch (strict in-hunk only); `0.0` admits every out-of-hunk P2+. |
314
+
|`domain_critic_cap`|`3`| How many domain critics may spawn across the required and best-effort buckets combined. `source: "core"` reviewers (Design Critic, Impact Analyzer) are exempt. **Setting the value to `0` spawns no domain critics at all (kill switch).** Invalid entries (wrong type, negative) silently fall back to the default. Also overridable per-run with `arbitrate-budget --domain-critic-cap`. |
315
+
316
+
**When to raise `domain_critic_cap`.** The cap drops by `(priority asc, reviewer asc)`. A repo whose `critic-gates.json` still uses the legacy `moduleCritics[]` schema gets every entry migrated as `required: False` with **no**`priority`, so all of them sit at the default `2` and the tiebreak degenerates to **alphabetical by reviewer name** — systematically favoring early names over relevance, and cutting the very critic the coverage critic proposed *for* the diff. Raising the cap is the blunt remedy; the precise one is migrating the relevant rules to the canonical `coverage[]` schema, which supports explicit `priority` and `required` (see `_migrate_module_critics` for what the legacy form forces).
313
317
314
318
The chosen mode + count surface in `partitions.json` (`partition_mode`, `partition_count`, `total_changed_loc`, `unified_threshold_loc`), propagate into `verify_manifest.json`, and render in both presenters (local-mode Verifier Stats footer and GitHub Step 6e). Under partitioned mode, `stats.verification.by_reviewer` splits BHA findings per partition (`bha_p0`, `bha_p1`, …) so an over-rejecting partition surfaces in the FP-rate column.
Copy file name to clipboardExpand all lines: plugins/code-review/commands/start.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,7 +32,7 @@ Run a multi-agent code review with partitioned deep review, deterministic hygien
32
32
The `--depth` flag selects which reviewer fleet runs. Default `standard`. Bare `/start` invocations preserve historical behavior.
33
33
34
34
-**shallow** — hygiene + BHA (partitioned at >5000 LOC) + BHB + unified_auditor + verifier. Skips signal extraction, coverage planning/critic, and all `critic-gates.json` entries. Static spawn spec; no routing/critic decisions. Hygiene emits a `tier_mismatch_nudge` MEDIUM finding (category `Coverage`) when the PR's diff size, schema/migration paths, or public API surface suggest standard would catch more.
35
-
-**standard** — current behavior. Full fleet with signal-driven routing, coverage critic, repo-specific critic activation via `critic-gates.json`. Budget arithmetic reserves BHA partitions FIRST (Phase 4) and caps total domain critics across both required and best-effort buckets at the tier-uniform `DOMAIN_CRITIC_CAP = 3` (standard and deep alike). Required critics dropped by the cap emit coverage-gap findings.
35
+
-**standard** — current behavior. Full fleet with signal-driven routing, coverage critic, repo-specific critic activation via `critic-gates.json`. Budget arithmetic reserves BHA partitions FIRST (Phase 4) and caps total domain critics across both required and best-effort buckets at the tier-uniform `DOMAIN_CRITIC_CAP` (default 3, standard and deep alike; operator-tunable via `.closedloop-ai/settings/code-review.json:domain_critic_cap`, or per-run with `arbitrate-budget --domain-critic-cap`). Required critics dropped by the cap emit coverage-gap findings.
36
36
- **deep** — standard plus two deep-only conditional core reviewers. The always-on **Design Critic** runs on every deep review (no trigger): a software-design craftsmanship reviewer covering module depth/information hiding, SOLID, dependency direction and layer boundaries, and project structure (drawing on *A Philosophy of Software Design*, SOLID, and *Clean Architecture*); it is `source: "core"` so it is exempt from `DOMAIN_CRITIC_CAP`, runs on Sonnet, is graph-aware (queries the `codebase-memory-mcp` knowledge graph via `get_architecture`/`query_graph` when the repo is indexed, else grep), and emits `category: "Code Quality"` findings scoped to design flaws this change introduces or worsens. The signal-gated **Impact Analyzer** (FEA-1401), a cross-file blast-radius reviewer, runs when signal extraction detects `exported_symbol_change` or `symbol_deletion`. The analyzer identifies changed exported symbols, finds external usages outside the diff (via the `codebase-memory-mcp` knowledge graph when the repo is indexed, else grep), and emits findings with `external_impact[]` listing every callsite that breaks under the new signature. Cost-capped at 30 symbols × 50 callsites with a 5-minute wall budget; deferred symbols surface in the Coverage Plan footer. Impact findings carry `category: "ImpactAnalysis"` and are verifier-audited per-entry (cited callsites read, snippet content-matched, grep replayed). ≥2 verified BLOCKING/HIGH Impact findings escalate the verdict to `NEEDS_ATTENTION` (Rule 6). Deep's extra breadth comes from these two reviewers rather than a wider domain-critic cap.
37
37
38
38
Tier transitions are detected via `review_state.json`: a cached `shallow` review does not satisfy a subsequent `standard` invocation — the deeper run actually executes the previously skipped reviewers.
@@ -346,7 +346,7 @@ These conditions mirror the cache-update gate (Gate C) and the pre-Phase-4b "Rev
346
346
347
347
## Operator Settings
348
348
349
-
Two optional operator-authored config files live under `.closedloop-ai/settings/`. Both are absent by default; the pipeline uses built-in defaults until they exist.
349
+
Three optional operator-authored config files live under `.closedloop-ai/settings/`. All are absent by default; the pipeline uses built-in defaults until they exist.
Copy file name to clipboardExpand all lines: plugins/code-review/tools/python/config/cli.json
+21-3Lines changed: 21 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -408,7 +408,11 @@
408
408
"flags": [
409
409
"--depth"
410
410
],
411
-
"choices": ["shallow", "standard", "deep"],
411
+
"choices": [
412
+
"shallow",
413
+
"standard",
414
+
"deep"
415
+
],
412
416
"help": "Invocation tier (FEA-1401). Gates COVERAGE_CORE_CONDITIONAL reviewers like the Impact Analyzer."
413
417
}
414
418
]
@@ -1437,6 +1441,20 @@
1437
1441
"deep"
1438
1442
],
1439
1443
"help": "Invocation tier; validated for hygiene. The per-source domain-critic cap is tier-uniform; deep's extra breadth comes from the always-on conditional core reviewers (Design Critic, Impact Analyzer)"
1444
+
},
1445
+
{
1446
+
"flags": [
1447
+
"--settings"
1448
+
],
1449
+
"default": null,
1450
+
"help": "Path to code-review.json operator settings (default .closedloop-ai/settings/code-review.json); overridable for test isolation"
1451
+
},
1452
+
{
1453
+
"flags": [
1454
+
"--domain-critic-cap"
1455
+
],
1456
+
"type": "int",
1457
+
"help": "Override the domain-critic cap (>=0; 0 spawns no domain critics). Takes precedence over code-review.json domain_critic_cap and the built-in default"
1440
1458
}
1441
1459
]
1442
1460
},
@@ -1463,7 +1481,7 @@
1463
1481
},
1464
1482
{
1465
1483
"name": "derive-static-spec",
1466
-
"help": "Emit a static spawn.json.spec for shallow-tier runs (BHA × N partitions + BHB + unified_auditor); arbitrate_status=\"static\"",
1484
+
"help": "Emit a static spawn.json.spec for shallow-tier runs (BHA \u00d7 N partitions + BHB + unified_auditor); arbitrate_status=\"static\"",
0 commit comments