codereview-loop 0.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codereview/__init__.py +6 -0
- codereview/__main__.py +4 -0
- codereview/acceptance.py +649 -0
- codereview/agentsmd.py +259 -0
- codereview/bench.py +881 -0
- codereview/claims.py +182 -0
- codereview/cli.py +2927 -0
- codereview/core.py +9070 -0
- codereview/crash.py +247 -0
- codereview/discovery.py +289 -0
- codereview/disputes.py +749 -0
- codereview/diversity.py +183 -0
- codereview/evidence.py +1023 -0
- codereview/feedback.py +416 -0
- codereview/github.py +286 -0
- codereview/hardening.py +45 -0
- codereview/herdrhost.py +373 -0
- codereview/hooks.py +261 -0
- codereview/intake.py +208 -0
- codereview/mcp_tools.py +455 -0
- codereview/mcp_transport.py +272 -0
- codereview/notify.py +237 -0
- codereview/pilot.py +549 -0
- codereview/policy.py +1086 -0
- codereview/probe.py +534 -0
- codereview/providers.py +1681 -0
- codereview/record_schema.py +904 -0
- codereview/registry.py +294 -0
- codereview/risk.py +368 -0
- codereview/sarif.py +309 -0
- codereview/seatstate.py +398 -0
- codereview/setup_wizard.py +355 -0
- codereview/support.py +328 -0
- codereview/techlead.py +1041 -0
- codereview/tiering.py +265 -0
- codereview/userconfig.py +307 -0
- codereview_loop-0.13.0.dist-info/METADATA +502 -0
- codereview_loop-0.13.0.dist-info/RECORD +44 -0
- codereview_loop-0.13.0.dist-info/WHEEL +5 -0
- codereview_loop-0.13.0.dist-info/entry_points.txt +3 -0
- codereview_loop-0.13.0.dist-info/licenses/LICENSE +21 -0
- codereview_loop-0.13.0.dist-info/top_level.txt +2 -0
- reviewloop/__init__.py +6 -0
- reviewloop/__main__.py +6 -0
codereview/diversity.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""codereview panel diversity — Epic E3 enforcement.
|
|
3
|
+
|
|
4
|
+
The check operates on the COMPOSED panel for a run — the seats
|
|
5
|
+
handed to core.run_review, before any of them is called — and
|
|
6
|
+
answers two questions:
|
|
7
|
+
|
|
8
|
+
1. Does the panel span at least N distinct vendor families?
|
|
9
|
+
(N = `[diversity] min_families` in the project policy.)
|
|
10
|
+
2. If the builder's own vendor family is on the panel, can it
|
|
11
|
+
be excluded without dropping the panel below that minimum?
|
|
12
|
+
(Only when the policy opts in: `[diversity]
|
|
13
|
+
exclude_builder_family`.)
|
|
14
|
+
|
|
15
|
+
Families come from seat metadata — the registry family tags the
|
|
16
|
+
seats were built with, or the operator's --seat-meta override —
|
|
17
|
+
never from a seat's display name. A seat whose family is
|
|
18
|
+
'unknown' (a fully custom spec) never counts toward the minimum:
|
|
19
|
+
the same convention policy.evaluate_policy applies to its
|
|
20
|
+
post-hoc `panel.min_families` rule. The two rules are distinct
|
|
21
|
+
on purpose: [diversity] judges the panel a run BRINGS (this
|
|
22
|
+
module, at composition); [panel] min_families judges the seats
|
|
23
|
+
that actually SERVED (policy.evaluate_policy, after the round).
|
|
24
|
+
|
|
25
|
+
Builder identity: run_review's `builder_family` argument is the
|
|
26
|
+
only input. No run path in the CLI knows the builder's family
|
|
27
|
+
today — a --builder-cmd is an opaque command string — so there
|
|
28
|
+
the exclusion simply never engages; this module never invents a
|
|
29
|
+
builder identity from a command line, an author string, or a
|
|
30
|
+
diff. When a future caller knows the family, it passes it and
|
|
31
|
+
the exclusion applies, recorded like everything else here.
|
|
32
|
+
|
|
33
|
+
Exclusion is a composition act, not a lens act: an excluded
|
|
34
|
+
seat is removed from the panel before tasks are derived, and
|
|
35
|
+
its lens is NEVER reassigned by this module. With an explicit
|
|
36
|
+
seat->lens binding, the existing S1 machinery treats the
|
|
37
|
+
excluded seat exactly like any absent seat — the lens is served
|
|
38
|
+
by its configured fallback or the run degrades with a
|
|
39
|
+
'lens unserved' cause. With legacy seat-order assignment, the
|
|
40
|
+
remaining seats fill the lenses by the ordinary rule.
|
|
41
|
+
|
|
42
|
+
Outcomes (core.run_review wires them): the assessment is
|
|
43
|
+
recorded verbatim in the report's `diversity` section and as an
|
|
44
|
+
applied `diversity.min_families` rule in the policy section. A
|
|
45
|
+
violation labels the run degraded with the cause
|
|
46
|
+
'panel diversity below minimum'. Under `[diversity] enforce =
|
|
47
|
+
"degrade"` (the default) that is all: the violation is recorded
|
|
48
|
+
as an ADVISORY policy violation and cannot change the gate.
|
|
49
|
+
Under `enforce = "block"` it is additionally a blocking policy
|
|
50
|
+
violation, gate-changing exactly like any other.
|
|
51
|
+
|
|
52
|
+
With no [diversity] configuration (or no policy at all) the
|
|
53
|
+
check does not run: no record section, no applied rule, no
|
|
54
|
+
behaviour change — byte-identical to before Epic E3.
|
|
55
|
+
|
|
56
|
+
Deterministic and pure: no model calls, no I/O. Verification
|
|
57
|
+
rounds are out of scope — run_verification carries no project
|
|
58
|
+
policy today, so there is no diversity surface there either.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
from __future__ import annotations
|
|
62
|
+
|
|
63
|
+
UNKNOWN_FAMILY = "unknown"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _norm_family(fam):
|
|
67
|
+
"""P2-03: family tags are operator-typed and compared
|
|
68
|
+
case-insensitively — 'OpenAI', 'openai' and ' openai ' are
|
|
69
|
+
the one family. Normalisation lives ONLY at this boundary:
|
|
70
|
+
counting and exclusion compare normalised forms, and the
|
|
71
|
+
tags stored anywhere else are never rewritten."""
|
|
72
|
+
return str(fam).strip().casefold() if fam else ""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def known_families(seat_families):
|
|
76
|
+
"""The distinct KNOWN vendor families in a {seat: family}
|
|
77
|
+
mapping, sorted. 'unknown'/empty tags never count — a panel
|
|
78
|
+
of untagged seats has zero provable diversity."""
|
|
79
|
+
return sorted({fam for fam in
|
|
80
|
+
(_norm_family(f) for f in seat_families.values())
|
|
81
|
+
if fam and fam != UNKNOWN_FAMILY})
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def policy_config(policy):
|
|
85
|
+
"""The effective [diversity] configuration of a loaded
|
|
86
|
+
policy dict, or None when the check is not configured (no
|
|
87
|
+
policy, no table, or the table at its defaults: minimum 0
|
|
88
|
+
and exclusion off). `enforce` defaults to 'degrade'."""
|
|
89
|
+
if not policy:
|
|
90
|
+
return None
|
|
91
|
+
div = policy.get("diversity") or {}
|
|
92
|
+
min_families = div.get("min_families") or 0
|
|
93
|
+
exclude = bool(div.get("exclude_builder_family"))
|
|
94
|
+
if not min_families and not exclude:
|
|
95
|
+
return None
|
|
96
|
+
return {"min_families": int(min_families),
|
|
97
|
+
"exclude_builder_family": exclude,
|
|
98
|
+
"enforce": div.get("enforce") or "degrade"}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def assess_panel(seat_families, *, min_families=0,
|
|
102
|
+
builder_family=None, exclude_builder=False):
|
|
103
|
+
"""Assess one composed panel. `seat_families` maps seat
|
|
104
|
+
name -> family tag for every seat on the panel.
|
|
105
|
+
|
|
106
|
+
Returns the record-ready assessment:
|
|
107
|
+
|
|
108
|
+
min_families the configured minimum (0 = none)
|
|
109
|
+
builder_family the builder's family as given (or None)
|
|
110
|
+
families_before distinct known families, pre-exclusion
|
|
111
|
+
families distinct known families, post-exclusion
|
|
112
|
+
excluded_seats builder-family seats removed (sorted)
|
|
113
|
+
builder_excluded True when exclusion actually happened
|
|
114
|
+
builder_kept_reason why exclusion did not happen, when
|
|
115
|
+
it was requested but did not apply (None
|
|
116
|
+
when it applied or was not requested, and
|
|
117
|
+
when no panel seat carries the builder's
|
|
118
|
+
family — nothing was there to keep)
|
|
119
|
+
violation families < min_families (min > 0)
|
|
120
|
+
detail the one-line verdict, used verbatim in
|
|
121
|
+
the policy violation when there is one
|
|
122
|
+
"""
|
|
123
|
+
# P2-03: comparisons run on normalised family tags (see
|
|
124
|
+
# _norm_family); `bf` keeps the as-given form for the record.
|
|
125
|
+
seats = {name: _norm_family(fam)
|
|
126
|
+
for name, fam in seat_families.items()}
|
|
127
|
+
families_before = known_families(seats)
|
|
128
|
+
excluded = []
|
|
129
|
+
kept_reason = None
|
|
130
|
+
bf = str(builder_family).strip() if builder_family else None
|
|
131
|
+
bf_norm = _norm_family(builder_family)
|
|
132
|
+
if exclude_builder:
|
|
133
|
+
if not bf_norm or bf_norm == UNKNOWN_FAMILY:
|
|
134
|
+
kept_reason = ("builder family unknown — exclusion "
|
|
135
|
+
"cannot apply")
|
|
136
|
+
else:
|
|
137
|
+
builder_seats = sorted(
|
|
138
|
+
name for name, fam in seats.items()
|
|
139
|
+
if fam == bf_norm)
|
|
140
|
+
if builder_seats:
|
|
141
|
+
rest = {name: fam for name, fam in seats.items()
|
|
142
|
+
if fam != bf_norm}
|
|
143
|
+
if rest and len(known_families(rest)) \
|
|
144
|
+
>= min_families:
|
|
145
|
+
excluded = builder_seats
|
|
146
|
+
seats = rest
|
|
147
|
+
elif not rest:
|
|
148
|
+
kept_reason = ("excluding the builder's "
|
|
149
|
+
"family would empty the panel")
|
|
150
|
+
else:
|
|
151
|
+
kept_reason = (
|
|
152
|
+
"excluding the builder's family would "
|
|
153
|
+
"leave the panel below the configured "
|
|
154
|
+
f"minimum of {min_families} distinct "
|
|
155
|
+
"families")
|
|
156
|
+
families = known_families(seats)
|
|
157
|
+
violation = min_families > 0 and len(families) < min_families
|
|
158
|
+
if violation:
|
|
159
|
+
detail = (
|
|
160
|
+
f"composed panel spans {len(families)} distinct "
|
|
161
|
+
f"vendor families ({', '.join(families) or 'none'}); "
|
|
162
|
+
f"policy requires at least {min_families}")
|
|
163
|
+
elif min_families > 0:
|
|
164
|
+
detail = (
|
|
165
|
+
f"composed panel spans {len(families)} distinct "
|
|
166
|
+
f"vendor families ({', '.join(families) or 'none'}); "
|
|
167
|
+
f"policy minimum of {min_families} met")
|
|
168
|
+
else:
|
|
169
|
+
detail = (
|
|
170
|
+
f"composed panel spans {len(families)} distinct "
|
|
171
|
+
f"vendor families ({', '.join(families) or 'none'}); "
|
|
172
|
+
"no minimum configured")
|
|
173
|
+
return {
|
|
174
|
+
"min_families": int(min_families),
|
|
175
|
+
"builder_family": bf,
|
|
176
|
+
"families_before": families_before,
|
|
177
|
+
"families": families,
|
|
178
|
+
"excluded_seats": excluded,
|
|
179
|
+
"builder_excluded": bool(excluded),
|
|
180
|
+
"builder_kept_reason": kept_reason,
|
|
181
|
+
"violation": violation,
|
|
182
|
+
"detail": detail,
|
|
183
|
+
}
|