Record judgment coverage per score row, and publish the like-for-like trend - #23
Merged
Merged
Conversation
… trend The published score trend had the wrong sign. history.csv's 2026-05 row folds in no judgment overlay and its 2026-08 row folds one into every lecture; a lecture assessed against more rules scores lower, so the corpus mean "fell" 8.2 -> 7.7 and Writing 6.6 -> 4.6 while, on the evidence layer alone, the same lectures rose 8.2 -> 8.4 and 6.6 -> 7.1 (HIGH 102 -> 85). Every "Writing fell" sentence on the series pages described coverage, not the corpus. Two records make this checkable rather than remembered: - history.csv gains a `reviewed` column: the lectures in the row whose score folds in an overlay, counted by the draft's own rule (the overlay file exists). 2026-05 is backfilled at 0 — every overlay is stamped with a 2026-08 pin and the row never moved while they landed (VERIFICATION.md). - history_mechanical.csv is the same row from the evidence layer alone, summarised from scores_mechanical.csv: the reports drafted without --reviews into a throwaway root. Drafting *with* --reviews into that root reproduces the committed scores.csv byte for byte, so the two files come from one code path. 2026-05's twin is itself. qestyle_report --history writes both and exits if scores_mechanical.csv is absent. The gate's new score-history check holds every row to its coverage and its twin, and the newest period to what scores*.csv summarise to now (the score half of #21). qestyle_status prints both tables and flags a coverage change. The intro's generated coverage block states the cross-period case from the files, so the sentence cannot go stale under the numbers again. Prose corrected: README's like-for-like claim is scoped to rule reach; the five series narratives and details.md say what moved and on which basis, with per-series like-for-like figures verified against the CSVs. Runbook, both skills and CLAUDE.md carry the second draft and the rule: never compare score levels across periods whose `reviewed` differs. Checker digest unchanged; no scan, lexer or rule file touched. See #16. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a core interpretability flaw in the published score trend by recording judgment-layer coverage per history row (reviewed) and publishing a like-for-like, evidence-only twin history (history_mechanical.csv). It also updates the gate and generated/prose narrative so cross-period score comparisons are only made on a comparable basis.
Changes:
- Add
reviewedcoverage tolectures/data/history.csvand introducelectures/data/history_mechanical.csvderived fromscores_mechanical.csv. - Update the reporting and gate tooling to write/validate both histories and detect stale or inconsistent latest-period rows.
- Refresh documentation and series/front-page narratives to distinguish published (with overlays) vs evidence-only (mechanical) movements.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| UPDATE.md | Documents the required mechanical (no---reviews) draft/score step and explains how to interpret reviewed vs mechanical twins. |
| tools/VERIFICATION.md | Records verification basis for the 2026-05 backfill and the coverage-driven sign flip in the published trend. |
| tools/qestyle_status.py | Prints trend tables including reviewed and the like-for-like mechanical table, with a coverage-warning path. |
| tools/qestyle_report.py | Adds mechanical score/history outputs, writes reviewed, and generates per-period comparability admonitions. |
| tools/qestyle_check.py | Adds score-history gate: validates headers, twin presence, coverage bounds/sums, and latest-period staleness vs current scores*.csv. |
| ROADMAP.md | Updates design notes to include judgment-coverage comparability and the new mechanical twin record. |
| README.md | Corrects the like-for-like claim to apply to reach, and explains why score rows are not comparable without coverage alignment. |
| lectures/lecture-python.myst/index.md | Rewrites movement claims to cite evidence-only (mechanical) deltas when coverage differs. |
| lectures/lecture-python-programming/index.md | Same: clarifies published vs like-for-like movements and cites history_mechanical.csv. |
| lectures/lecture-python-intro/index.md | Same: updates trend interpretation to account for judgment coverage. |
| lectures/lecture-python-advanced.myst/index.md | Same: replaces “fall” narrative with coverage-aware like-for-like numbers. |
| lectures/lecture-dp/index.md | Same: attributes changes to judgment-layer landing and provides mechanical deltas. |
| lectures/intro.md | Updates the generated review-coverage block output to include cross-period comparability messaging. |
| lectures/details.md | Updates coverage prose to reflect complete current-pass coverage vs absent previous-pass coverage. |
| lectures/data/scores_mechanical.csv | Adds evidence-only per-lecture scores used to derive the mechanical history rows. |
| lectures/data/history.csv | Adds reviewed column per row (judgment overlays folded into scores). |
| lectures/data/history_mechanical.csv | Adds evidence-only per-period/per-series history rows for like-for-like score comparisons. |
| CLAUDE.md | Adds the “score row carries its coverage” non-negotiable convention and mechanical-twin guidance. |
| .claude/skills/pass-publish/SKILL.md | Updates publish workflow to generate scores_mechanical.csv and explains comparability rules. |
| .claude/skills/pass-measure/SKILL.md | Updates measure workflow to generate scores_mechanical.csv and explains comparability rules. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… coverage by rule check_score_history evaluated reviewed_counts() while building the loop tuple, before the os.path.exists guard on scores.csv, so a missing scores.csv crashed the gate instead of reporting FAIL score-history. It is computed inside the loop now, after the guard. qestyle_status flagged a coverage change only when the distinct `reviewed` counts differed, missing 100/110 vs 100/145, and validated only `reviewed` as digits. It now applies the rule the front page's generated block uses: rows are comparable only when every period is fully reviewed or none is. Equal counts and equal ratios are still two partially covered rows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #16, and the finding is stronger than the issue stated: the published score trend has the wrong sign.
history.csv's 2026-05 row folds in no judgment overlay; its 2026-08 row folds one into all 348 lectures (every overlay inreviews/is stamped with a 2026-08 pin, and the 2026-05 row never moved while they landed). A lecture assessed against more rules scores lower, so:history.csv)history_mechanical.csv)Per series, like for like, Writing was flat or up everywhere (intro 7.5 → 7.7, programming 5.7 → 5.7, python.myst 5.9 → 7.0, advanced 7.3 → 7.4, dp 7.0 → 7.0) where the Summary pages said it fell by 1.6–2.7 points. The mechanical draft is validated: drafting the pinned corpus with
--reviewsinto a scratch root reproduces the committedscores.csvbyte for byte; the same command without--reviewsisscores_mechanical.csv.What changes
Data (issue item 3, plus the like-for-like row).
history.csvgains areviewedcolumn — lectures in the row whose score folds in an overlay, by the draft's own rule (overlay file exists). Newhistory_mechanical.csv: the same rows from the evidence layer alone, summarised from a committedscores_mechanical.csv. Both written byqestyle_report.py --history, which now exits ifscores_mechanical.csvis absent. 2026-05 backfilled once by hand:reviewed=0, twin = itself; basis recorded intools/VERIFICATION.md.Gate. New
score-historycheck:reviewedpresent and in[0, lectures], series sum to TOTAL, every row has a twin and vice versa, areviewed=0row equals its twin, and the newest period's rows equal whatscores.csv/scores_mechanical.csvsummarise to now withreviewedmatching the overlays actually present — the score half of #21. Eight mutations tested, all caught with distinct messages.Front page (issue item 1 and 2). The generated
review-coverageblock now states the cross-period case from the files — not comparable, why, both sets of figures, and that the trend is reported on reach for that reason — so the sentence cannot go stale under the numbers again.qestyle_statusprints both tables and flags a coverage change.Prose corrected. README's like-for-like claim scoped to rule reach; the five series narratives and the
details.mdcoverage bullet (which still said coverage was partial) rewritten to say what moved and on which basis, every quoted figure verified against the CSVs by script. Runbook, both skills and CLAUDE.md carry the second draft step and the rule: never compare score levels across periods whoserevieweddiffers.The decision this takes (issue item 2)
Publish the score trend only like for like: the headline stays rule reach (already the case on the front page and charts), score rows carry their coverage, and the evidence-layer twin is what any cross-period score sentence quotes. Not chosen: re-reviewing 2026-05 (≈25 agent-hours to make the published rows comparable) — the evidence-layer row answers the question at zero cost, and the issue's own design note already argues reach is the honest headline.
Not in this PR
Checker digest unchanged (
aef064f3b260) — no scan, lexer or rule file touched, so no re-measure. The reach half of #21 (history rows vsrule_reach.csv) is still open. Nothing inreviews/or the per-lecture reports moved.🤖 Generated with Claude Code