Skip to content

Add matplotlib charts to README, generated by scripts/gen_readme_charts.py - #17

Merged
mattekudacy merged 3 commits into
mainfrom
claude/sweet-archimedes-q6zzjw
Sep 12, 2026
Merged

mattekudacy merged 3 commits into
mainfrom
claude/sweet-archimedes-q6zzjw

Conversation

@mattekudacy

Copy link
Copy Markdown
Owner

What does this change and why?

Adds five measured matplotlib/seaborn charts to README.md that visualize the classifier's performance across error corpora and failure modes. The charts are generated by a new script scripts/gen_readme_charts.py that:

  • Re-scores corpora A–E through the same RulesClassifier path scripts/classifier_accuracy.py uses
  • Derives the routing demo from scripts/bench_synthetic.py's own _task_body success logic
  • Marks two figures as HISTORICAL (corpus C's pre-tuning v1.0 score and LLMClassifier/HybridClassifier runs) that cannot be recomputed without a live model

The charts cannot drift from the README's tables — a rules.py change that moves a held-out number moves the charts on the next run.

Charts added:

  1. Routing demo: success rate per failure type (baseline vs. triage)
  2. Per-corpus accuracy: training vs. held-out scores across corpora A–E
  3. Held-out recall by group: self-healing vs. routing-sensitive types across corpora C/D/E
  4. Classifier comparison: RulesClassifier vs. LLMClassifier vs. HybridClassifier
  5. Corpus E signal split: which errors were caught by structured codes vs. message text

Related issue

None


Type of change

  • New feature (documentation/measurement)
  • Documentation

Checklist

  • No AI-attribution trailers or badges anywhere in this PR
  • pytest tests/ -x --tb=short passes locally
  • ruff check ., ruff format --check ., and mypy triage/ --strict are all clean
  • No new imports of optional deps inside triage/ core — matplotlib/seaborn added only to dev extra in pyproject.toml
  • README.md and CHANGELOG.md updated with the new charts and script documentation
  • scripts/README.md updated with chart generation instructions

Test Plan

The script re-scores the frozen corpora in tests/data/ through the same RulesClassifier path the test suite uses, so the numbers it produces are deterministic and match scripts/classifier_accuracy.py. Run:

PYTHONPATH=. python scripts/gen_readme_charts.py

The five PNG files are written to docs/assets/charts/ and embedded in README.md. Verify the charts render correctly in the README and that the accuracy numbers match the tables in the same document.

Anything reviewers should look at closely?

The routing_demo() function dynamically imports scripts/bench_synthetic.py to extract its TASKS and _task_body — this is intentional to avoid duplicating the synthetic task definitions. The function calls _task_body twice per task (once with no hint, once with the triage hint) to measure the recovery gap, matching the benchmark's own success logic.

The two HISTORICAL constants (corpus C's v1.0 pre-tuning score and LLMClassifier/HybridClassifier runs) are documented in the module docstring and marked in the code. They are sourced from docs/known-limitations.md and cannot be recomputed without a live model or re-tuning against held-out data.

https://claude.ai/code/session_01VYCX2qtGYVNsSUmtN6cipS

Adds five SVG charts to README.md and the stdlib-only generator that
produces them, scripts/gen_readme_charts.py:

  1. routing demo — success rate per failure type, both benchmark arms
  2. per-corpus accuracy — training vs held-out, in scoring order
  3. held-out recall by group across corpora C/D/E — the flat
     routing-sensitive line through a full tuning cycle
  4. Rules vs LLM vs Hybrid — recall bought, precision spent
  5. corpus E by code family — where the structural signal reaches

The generator does not transcribe the README's tables. It re-scores
corpora A-E through the same RulesClassifier path
classifier_accuracy.py uses, and derives the routing demo from
bench_synthetic.py's own _task_body, so a rules.py change that moves a
held-out number moves the charts on the next run. The two figures that
cannot be recomputed — corpus C's pre-tuning v1.0 score, and the
LLMClassifier/HybridClassifier runs that need a live model — are marked
HISTORICAL constants naming the document that recorded them.

No matplotlib and no new dependency: the SVGs are written by hand, each
with its own prefers-color-scheme block so one asset reads correctly in
both GitHub themes. Layout bands are measured from calibrated text
metrics rather than guessed, and row labels raise instead of silently
overlapping the plot.

Also adds the corpus E row (69% recall, 100% precision) to the block
table, which had stopped at corpus D, and corrects "Nine-block
measurement" to ten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VYCX2qtGYVNsSUmtN6cipS
…awn SVG

Replaces the stdlib-only SVG renderer in scripts/gen_readme_charts.py
with matplotlib + seaborn (whitegrid theme, deep palette, 200 DPI),
so the five README charts read like plots from a real experiment
rather than custom-drawn graphics. Output is now PNG.

Data sourcing is unchanged: every chart is still scored live against
the frozen corpora and derived live from bench_synthetic.py, with the
two truly historical figures (corpus C's pre-tuning score, the LLM/
Hybrid runs) still marked HISTORICAL with their source.

matplotlib/seaborn are added to the dev extra only — not a runtime
dependency of triage itself, same footing as anthropic/openai for the
other scripts. README image links updated from .svg to .png.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VYCX2qtGYVNsSUmtN6cipS
…es-q6zzjw

Resolves two conflicts, both independently-added entries at the same
list position (no logical overlap):
- CHANGELOG.md: kept both "Added" entries (charts, MAST pilot corpus)
- scripts/README.md: kept both additions (Charts section, MAST pilot
  paragraph), reordered so the MAST paragraph continues its existing
  section before the new Charts section starts

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VYCX2qtGYVNsSUmtN6cipS
@mattekudacy
mattekudacy merged commit 6e133ba into main Sep 12, 2026
6 of 7 checks passed
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