qa(scores): amend false rc1/rc2 ledger claims, guard the claim class, land the lens-only ruler fence (#725) - #760
Conversation
…ens-only ruler fence (#725) Ledger/ruler integrity batch from the post-Sprint-1 adversarial audit: 1. AMEND the false claims (qa/scores_amend_rc1_rc2_notes.py, idempotent one-shot): - v1.0.4-rc2-c92a393 claimed "Same ruler sc_5ac7a1d9103c as rc1 (apples-to-apples)" while stamped sc_df34ecd02b4f — #739 changed assert_behavioral.py between recordings: CROSS-RULER, a re-baseline (LENS prose comparison still informative). - v1.0.4-rc1-fa97b34 claimed "ui_audit FAIL(axe)" — the VM log shows axe NEVER RAN (browser-driver-manager missing, silent WARN-skip); actual FAILs were launcher play_reachable + merchant art_present placeholders. Ledger re-rendered. 2. GUARD the false-claim class: scores_db.add_run now raises ValueError when notes cite a ruler hash (sc_/lc_ + 12 hex) that differs from the row's stamped version. 3. LAND #725 (lens-only ruler fence): LENS_CONFIG_FILES (the 8 lens-relevant files = full ruler minus release_readiness.py) + lens_config_version() (lc_ prefix); add_run stamps both (additive lens_config_version column via the existing ALTER path; lens stays NULL when the full ruler is pinned — no false current-lens stamp on backfills); compare_rc fences the engine-duo trend on the LENS ruler (falling back to the full ruler for pre-lens rows) and gains --compare-rc-surface to show GUI-built-app RC rows fenced on the FULL ruler. Closes #725
📝 WalkthroughWalkthroughThis PR introduces a lens ruler—a quality-trend-fencing mechanism that excludes release-readiness-gate-only changes—alongside the existing full scoring ruler. It updates hashing, database persistence, run stamping, RC comparison fencing, CLI, documentation, and test coverage to implement lens-aware tracking and prevent non-apples-to-apples comparisons. ChangesLens ruler: foundation through testing
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
qa/test_scores_db_comparability.py (1)
128-128: 💤 Low valuePrefer
next()over list slice for single-element lookup.Both lines use list comprehension with
[0]indexing to find a single row.next()is more idiomatic and avoids building an intermediate list.♻️ Proposed refactor
- legacy = [r for r in scores_db.fetch_rows(db) if r["run_id"] == "legacy"][0] + legacy = next(r for r in scores_db.fetch_rows(db) if r["run_id"] == "legacy")- r2 = [x for x in scores_db.fetch_rows(db) if x["run_id"] == "old2"][0] + r2 = next(x for x in scores_db.fetch_rows(db) if x["run_id"] == "old2")Also applies to: 196-196
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@qa/test_scores_db_comparability.py` at line 128, Replace the list-comprehension + [0] single-element lookups with next() generator expressions to avoid building an intermediate list: change the assignment to legacy (currently using [r for r in scores_db.fetch_rows(db) if r["run_id"] == "legacy"][0]) to use next(r for r in scores_db.fetch_rows(db) if r["run_id"] == "legacy") and make the analogous replacement for the other single-row lookup at the second occurrence (line ~196); if you want to handle missing rows gracefully, pass a default to next(...) or wrap it in a clear error message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@qa/test_scores_db_comparability.py`:
- Line 128: Replace the list-comprehension + [0] single-element lookups with
next() generator expressions to avoid building an intermediate list: change the
assignment to legacy (currently using [r for r in scores_db.fetch_rows(db) if
r["run_id"] == "legacy"][0]) to use next(r for r in scores_db.fetch_rows(db) if
r["run_id"] == "legacy") and make the analogous replacement for the other
single-row lookup at the second occurrence (line ~196); if you want to handle
missing rows gracefully, pass a default to next(...) or wrap it in a clear error
message.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a33836c3-b816-4904-ab19-16b12ca8a6e0
⛔ Files ignored due to path filters (1)
qa/scores.dbis excluded by!**/*.db
📒 Files selected for processing (5)
qa/scores_amend_rc1_rc2_notes.pyqa/scores_db.pyqa/scores_ledger.mdqa/scoring_config_version.pyqa/test_scores_db_comparability.py
What
P1 ledger/ruler integrity batch (3 small related fixes in
qa/), from the post-Sprint-1 adversarial audit. Closes #725.1. Amend the false ledger claims (
qa/scores_amend_rc1_rc2_notes.py— idempotent one-shot, db + ledger re-rendered)v1.0.4-rc2-c92a393notes claimed "Same ruler sc_5ac7a1d9103c as rc1 (apples-to-apples)" — false: the row itself is stampedsc_df34ecd02b4f. Verified by recomputing the ruler hash from git history: rc1's stamp matches the ruler state ata104f1e(post-fix(rri): restore main()'s build_shas — #723 regression that crashed every RRI rollup #728), and fix(engine): companion location/XP sync — de-facto companions co-locate AND co-earn (#353) #739 changedqa/assert_behavioral.py(aSCORING_CONFIG_FILESmember) before the rc2 recording. Amended to: CROSS-RULER, the LENS prose comparison is still informative, but the BEHAVIORAL-capped lens comparability is a re-baseline.v1.0.4-rc1-fa97b34notes claimed "ui_audit FAIL(axe)" — false: the VM log (worldos-qa-results-fa97b34/results/ui_audit.loglines 32–33) shows axe never ran (browser-driver-managermissing → silent WARN-skip). The actual FAILs were launcherplay_reachable(no Resume/Continue CTA @1366+@1512) and merchantart_present(placeholders=4 > cap 2). Amended accordingly.Both amendments carry an explicit
[AMENDED 2026-06-10: …]tag — the ledger shows the correction, not a silent rewrite.2. Guard the false-claim class (
scores_db.add_run)add_runnow raisesValueErrorwhennotescite a ruler hash (sc_/lc_+ 12 hex) that differs from the row's stamped version. The exact rc2 incident is a test case. To reference another run's ruler, cite itsrun_id, not its hash.3. Land #725 — the lens-only ruler fence
qa/scoring_config_version.py:LENS_CONFIG_FILES= the 8 lens-relevant files (3 rubrics incl.rubric_angry_dm.src.md, 3 schemas,assert_behavioral.py) =SCORING_CONFIG_FILESminusrelease_readiness.py;lens_config_version()with the same hashing (distinctlc_prefix so a lens hash can never be confused with — or false-trip the guard against — a full-rulersc_hash); CLI--lens.qa/scores_db.py: additivelens_config_versioncolumn (existing_ensure_schemaALTER path; old rows read NULL).add_runstamps both versions; when the full ruler is pinned (backfill), the lens stamp stays NULL unless also pinned — stamping today's lens hash onto an old run would itself be a false claim.compare_rcnow fences the engine-duo trend on the LENS ruler (falls back to the full ruler for pre-lens rows — conservative: may split more than needed, never falsely merges). An RRI-gate-only edit (the fix(rri): scope native_gate build-SHA contract to the canonical release personas #723/fix(rri): restore main()'s build_shas — #723 regression that crashed every RRI rollup #728 case) no longer false-fences the lens trend.--compare-rc-surface: shows GUI-built-app RC rows (the RRI sweeps, incl. rc1/rc2) in their own blocks, fenced on the FULL ruler — the RRI is produced byrelease_readiness.py, which IS in that ruler.Verification
uv run --directory servers/engine python -m pytest ../../qa/test_scores_db_comparability.py ../../qa/test_release_readiness.py ../../qa/test_scores_db.py -q -p no:xdist→ 65 passed.bash qa/fast_gate.sh→ PASS (188 deterministic engine tests).sc_df34ecd02b4fbefore and after — none of the changed files is aSCORING_CONFIG_FILESmember). Current lens ruler:lc_4f7b718f3eb1.qa/scores.dbitself: no row's notes may cite a hash differing from its stamp, and the rc1/rc2 rows must carry the amended truth.Invariants
Additive only (new column via ALTER, old rows read NULL); no wire contracts touched; engine untouched.
Summary by CodeRabbit
Documentation
New Features
Bug Fixes
Tests