Skip to content

Record judgment coverage per score row, and publish the like-for-like trend - #23

Merged
mmcky merged 2 commits into
mainfrom
fix/score-trend-like-for-like
Sep 1, 2026
Merged

mmcky merged 2 commits into
mainfrom
fix/score-trend-like-for-like

Conversation

@mmcky

@mmcky mmcky commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

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 in reviews/ 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:

basis 2026-05 2026-08
published (history.csv) 8.2 · Writing 6.6 · HIGH 102 7.7 · Writing 4.6 · HIGH 197
evidence layer alone (history_mechanical.csv) 8.2 · Writing 6.6 · HIGH 102 8.4 · Writing 7.1 · HIGH 85

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 --reviews into a scratch root reproduces the committed scores.csv byte for byte; the same command without --reviews is scores_mechanical.csv.

What changes

Data (issue item 3, plus the like-for-like row). history.csv gains a reviewed column — lectures in the row whose score folds in an overlay, by the draft's own rule (overlay file exists). New history_mechanical.csv: the same rows from the evidence layer alone, summarised from a committed scores_mechanical.csv. Both written by qestyle_report.py --history, which now exits if scores_mechanical.csv is absent. 2026-05 backfilled once by hand: reviewed=0, twin = itself; basis recorded in tools/VERIFICATION.md.

Gate. New score-history check: reviewed present and in [0, lectures], series sum to TOTAL, every row has a twin and vice versa, a reviewed=0 row equals its twin, and the newest period's rows equal what scores.csv / scores_mechanical.csv summarise to now with reviewed matching 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-coverage block 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_status prints 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.md coverage 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 whose reviewed differs.

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 vs rule_reach.csv) is still open. Nothing in reviews/ or the per-lecture reports moved.

🤖 Generated with Claude Code

… 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>
Copilot AI lite review requested due to automatic review settings September 1, 2026 00:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 reviewed coverage to lectures/data/history.csv and introduce lectures/data/history_mechanical.csv derived from scores_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.

Comment thread tools/qestyle_check.py Outdated
Comment thread tools/qestyle_status.py Outdated
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants