Commit 47c6c6b
committed
feat(delphi): D10 — Clojure-parity rep comment selection (PR 8)
Replaces the pre-D10 botched-port `select_rep_comments_df` with a
single-pass reduce that mirrors Clojure `select-rep-comments`
(math/src/polismath/math/repness.clj:212-281).
Sits on top of PR 14a in the spr stack.
## Helpers added (top-level in `repness.py`)
- `passes_by_test(s)` — Clojure `passes-by-test?` (repness.clj:165-170).
OR'd on (rat, pat) and (rdt, pdt) z-sig-90. NO `pa >= 0.5` gate; the
pre-D10 Python gate was an over-restriction with no Clojure analog.
- `beats_best_by_test(s, current_best_z)` — Clojure `beats-best-by-test?`
(repness.clj:133-139). Strict `>` on `max(rat, rdt)`.
- `beats_best_agr(s, current_best)` — Clojure `beats-best-agr?`
(repness.clj:142-162). Four-branch agree-priority logic:
1. na == 0 AND nd == 0 → reject.
2. current_best AND current_best.ra > 1.0 → compare 4-way signed product
`ra * rat * pa * pat`.
3. current_best (else, ra <= 1.0) → compare `pa * pat` only.
4. No current_best → accept if `z90(pat)` OR `(ra > 1.0 AND pa > 0.5)`.
`current_best` stores the RAW row (Clojure repness.clj:250) so the
ra/rat/pa/pat surface stays available across iterations.
- `_finalize_row_for_output(row, *, is_best_agree=False)` — Clojure
`finalize-cmt-stats` (repness.clj:173-188) + best-agree flagging
(repness.clj:262-264). Emits `best_agree=True` and `n_agree=na` for the
best-agree slot.
## `select_rep_comments_df` rewrite
Signature now: `(stats_df, mod_out=None) -> List[Dict[str, Any]]`. Drops
the `agree_count` / `disagree_count` kwargs (Clojure has only a cap of 5).
Per-row state `{sufficient, best, best_agree}` updated by the helpers.
Final assembly: dedup best_agree from sufficient → sort by metric
(agree_metric for repful=='agree', disagree_metric for 'disagree')
→ prepend finalized+flagged best_agree → take 5 → agrees-before-disagrees.
The caller in `conv_repness` drops the `_stats_row_to_dict` wrapping step
(the new function returns finalized dicts directly).
## Two pre-D10 bugs fixed alongside the rewrite
- `pa >= 0.5 / pd >= 0.5` over-gate in the passing filter — removed (no
Clojure analog).
- "Fill from other category" + "first row" fallback blocks — deleted. The
`:best` / `:best_agree` mechanism IS the Clojure fallback.
## Tests (18 new in `tests/test_discrepancy_fixes.py`)
- TestD10PassesByTest (4): agree-side, disagree-side, neither, no pa-gate.
- TestD10BeatsBestByTest (3): None-best, max(rat,rdt), strict `>`.
- TestD10BeatsBestAgr (6): one per Clojure branch + boundary.
- TestD10SelectRepCommentsBoundary (5): empty input, single unvoted row
→ best fallback, sufficient-empty-best-agree-only, take-5 cap +
agrees-before-disagrees, **the eviction edge case** (best_agree outside
sufficient evicting 5th-highest-metric).
## Eviction edge case — flagged
`take(5)` runs AFTER prepending best_agree. If `best_agree` was kept by
`beats_best_agr` as a non-significant agree-priority fallback (failed
`passes_by_test`, qualified via Branch 4) AND `:sufficient` already has 5
entries, the prepend pushes total to 6 and `take(5)` evicts the
5th-highest-metric sufficient entry — possibly a strong dissenting view.
Mirrors Clojure exactly for blob parity. `# TODO(parity-eviction)` comment
at the take(5) site in the production code; entry added under
"Pending — needs team discussion" in PLAN.md; pinned by the synthetic
test above.
## Re-xfailed with updated reasons (D14 / D1 upstream divergence)
Six per-shared-(gid, tid) blob-comparison tests were previously xfailed as
"D5/D6/D7/D8/D10: no shared comments to compare". After D10 there ARE
shared comments (overlap ~20% on vw cold_start), but the per-(gid, tid)
stats still mismatch because Python and Clojure place different
participants in the "same" group ID. That's upstream PCA/KMeans
group-membership divergence (D14 / D1), not D10. Updated xfail reasons
point at D14 / D1. D10 itself is verified by the 18 synthetic tests.
Affected: TestD9ZScoreThresholds::test_z_values_match_clojure,
TestD5ProportionTest::test_pat_values_match_clojure_blob,
TestD6TwoPropTest::test_rat_values_match_clojure_blob,
TestD7RepnessMetric::test_repness_metric_matches_clojure_blob,
TestD8FinalizeStats::test_repful_matches_clojure_blob,
TestD10RepCommentSelection::test_rep_comments_match_clojure.
## Suite delta
- Pre (post-14a baseline): 295 passed, 12 skipped, 58 xfailed.
- Post: 313 passed, 12 skipped, 58 xfailed.
- Delta: +18 passed (the 18 new D10 synthetic tests), 0 failed, no new
xfailed.
## Documentation
- `delphi/docs/PLAN_DISCREPANCY_FIXES.md`: PR 14a row marked landed
(#2564), PR 8 (D10) marked in-flight, eviction concern added to
"Pending — needs team discussion".
- `delphi/docs/CLJ-PARITY-FIXES-JOURNAL.md`: "Session: PR 8 — D10 rep
comment selection (2026-06-11)" entry with full scope, suite delta,
and decisions log pointer.
## /goal mode
This PR is part of an autonomous run (`/goal`) targeting D10 + D11 + D12 +
golden snapshots as a stacked PR series. Decisions made autonomously
(key naming, return type, etc.) are documented in
`~/polis/D10_D11_D12_GOLDENS_DECISIONS.md` for batch user review at the
end of the run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commit-id:1b681fef1 parent 05dae1d commit 47c6c6b
4 files changed
Lines changed: 623 additions & 104 deletions
File tree
- delphi
- docs
- polismath/pca_kmeans_rep
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1347 | 1347 | | |
1348 | 1348 | | |
1349 | 1349 | | |
| 1350 | + | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
| 1373 | + | |
| 1374 | + | |
| 1375 | + | |
| 1376 | + | |
| 1377 | + | |
| 1378 | + | |
| 1379 | + | |
| 1380 | + | |
| 1381 | + | |
| 1382 | + | |
| 1383 | + | |
| 1384 | + | |
| 1385 | + | |
| 1386 | + | |
| 1387 | + | |
| 1388 | + | |
| 1389 | + | |
| 1390 | + | |
| 1391 | + | |
| 1392 | + | |
| 1393 | + | |
| 1394 | + | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
| 1412 | + | |
| 1413 | + | |
| 1414 | + | |
| 1415 | + | |
| 1416 | + | |
| 1417 | + | |
| 1418 | + | |
| 1419 | + | |
| 1420 | + | |
| 1421 | + | |
| 1422 | + | |
| 1423 | + | |
| 1424 | + | |
| 1425 | + | |
| 1426 | + | |
| 1427 | + | |
| 1428 | + | |
| 1429 | + | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
32 | | - | |
| 31 | + | |
| 32 | + | |
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| |||
915 | 915 | | |
916 | 916 | | |
917 | 917 | | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
0 commit comments