feat: add trend history and ribbons (task 0006) #6

Merged
alexion merged 1 commits from task-0006-trend-history-and-ribbons into main 2026-07-24 16:41:33 -04:00
Owner

Task file: .claude/tasks/0006-trend-history-and-ribbons.md

Summary

Adds the longitudinal layer to the benchmark deterministic core (skills/benchmark-skill/core/benchmark_core.py):

  • History — an opt-in --history JSON-lines file that appends one summary line per run (each axis's net margin and pass/fail plus the two-arm/three-arm flag) and trims oldest-first at fifty. It lives in the git-ignored tests/.reports/ directory and is ephemeral.
  • Trend ribbons — two stacked net-margin sparklines (Efficacy and Regression) over the last ~7 runs, verdict-colored dots, the current run ringed, and a net/delta/green-count readout. The Regression ribbon leaves a gap for any two-arm run.
  • Fragility chips — a green Efficacy badge chips its narrowest passing case, a green Regression badge chips every case at exactly one loss, and a case fragile on both carries both. A clean run still rests fully collapsed.

The runner's SKILL.md gains the --history argument and describes the ribbons and chips. Two committed fixtures (clean-bundle.json, fragile-bundle.json, machine-generated) and new checks/benchmark-core.nix sections cover the append-and-trim, both ribbons including the two-arm gap, and the per-badge chips. nix flake check passes.

Deviations / decisions

  • History persistence is the core's only side effect and is opt-in via --history; without it the core stays a pure transform and renders no ribbons.
  • The ribbon delta compares against the previous run that carries a value on the axis, skipping a two-arm gap rather than blanking the readout, consistent with the spec accepting regression discontinuity.
  • The green-count readout shows green/applicable, where the denominator excludes runs a given axis cannot score (two-arm runs on the regression axis).
  • The efficacy chip is a single case (narrowest, ties broken by authored order); the regression chip is every case at exactly one loss — following the task's comparative-vs-absolute wording.

Review

Overall: LOW

  • Blast radius: Low — additive --history flag and new render helpers in one file plus its test, no existing callers change behavior.
  • Reversibility: Low — history file is git-ignored and ephemeral, no migrations or published schema.
  • Test coverage: Low — the nix fixture check exercises the clean run, append-and-trim to 50, the two-arm ribbon gap, and independent per-badge chips.
  • Sensitive domain: Low — no auth/payments/permissions, the only side effect is a single-process read-then-rewrite of a local file.
  • Size & complexity: Medium — ~250 lines of new logic plus ~1200 lines of generated fixtures, simple control flow with real SVG/gap edge cases.
  • Runtime criticality: Low — dev-only benchmarking tooling, offline, not on any production path.

Standards — unaddressed

All semicolon-in-comment hard violations were fixed (in the diff). Left unaddressed, deliberately:

  • Docstring sentence-per-line — kept wrapping normally to match the file's established docstring style; the one-sentence-per-line rule was applied to the # comments, which were fixed.
  • Baseline smells (Message Chains via nested dict access, Primitive Obsession on bare chip/point dicts) — left as-is because they match the module's existing dict-of-dicts model; adding a type layer would diverge from the surrounding code.

Spec — unaddressed

The Spec axis found no missing or wrong requirements; the following are accepted deliberate deviations, each already noted above:

  • Delta vs. previous valued run, not the literal previous line — deliberate, skips two-arm gaps, consistent with the spec's accepted regression discontinuity.
  • green/applicable denominator in the readout — deliberate, reads more honestly than counting unscoreable two-arm runs against the total.
  • Faint dashed zero baseline in the sparkline — a readability aid not requested by the spec, harmless.
Task file: `.claude/tasks/0006-trend-history-and-ribbons.md` ## Summary Adds the longitudinal layer to the benchmark deterministic core (`skills/benchmark-skill/core/benchmark_core.py`): - **History** — an opt-in `--history` JSON-lines file that appends one summary line per run (each axis's net margin and pass/fail plus the two-arm/three-arm flag) and trims oldest-first at fifty. It lives in the git-ignored `tests/.reports/` directory and is ephemeral. - **Trend ribbons** — two stacked net-margin sparklines (Efficacy and Regression) over the last ~7 runs, verdict-colored dots, the current run ringed, and a net/delta/green-count readout. The Regression ribbon leaves a gap for any two-arm run. - **Fragility chips** — a green Efficacy badge chips its narrowest passing case, a green Regression badge chips every case at exactly one loss, and a case fragile on both carries both. A clean run still rests fully collapsed. The runner's `SKILL.md` gains the `--history` argument and describes the ribbons and chips. Two committed fixtures (`clean-bundle.json`, `fragile-bundle.json`, machine-generated) and new `checks/benchmark-core.nix` sections cover the append-and-trim, both ribbons including the two-arm gap, and the per-badge chips. `nix flake check` passes. ### Deviations / decisions - History persistence is the core's only side effect and is opt-in via `--history`; without it the core stays a pure transform and renders no ribbons. - The ribbon delta compares against the previous run that carries a value on the axis, skipping a two-arm gap rather than blanking the readout, consistent with the spec accepting regression discontinuity. - The green-count readout shows `green/applicable`, where the denominator excludes runs a given axis cannot score (two-arm runs on the regression axis). - The efficacy chip is a single case (narrowest, ties broken by authored order); the regression chip is every case at exactly one loss — following the task's comparative-vs-absolute wording. ## Review **Overall: LOW** - Blast radius: Low — additive `--history` flag and new render helpers in one file plus its test, no existing callers change behavior. - Reversibility: Low — history file is git-ignored and ephemeral, no migrations or published schema. - Test coverage: Low — the nix fixture check exercises the clean run, append-and-trim to 50, the two-arm ribbon gap, and independent per-badge chips. - Sensitive domain: Low — no auth/payments/permissions, the only side effect is a single-process read-then-rewrite of a local file. - Size & complexity: Medium — ~250 lines of new logic plus ~1200 lines of generated fixtures, simple control flow with real SVG/gap edge cases. - Runtime criticality: Low — dev-only benchmarking tooling, offline, not on any production path. ### Standards — unaddressed All semicolon-in-comment hard violations were fixed (in the diff). Left unaddressed, deliberately: - **Docstring sentence-per-line** — kept wrapping normally to match the file's established docstring style; the one-sentence-per-line rule was applied to the `#` comments, which were fixed. - **Baseline smells (Message Chains via nested dict access, Primitive Obsession on bare chip/point dicts)** — left as-is because they match the module's existing dict-of-dicts model; adding a type layer would diverge from the surrounding code. ### Spec — unaddressed The Spec axis found no missing or wrong requirements; the following are accepted deliberate deviations, each already noted above: - **Delta vs. previous *valued* run, not the literal previous line** — deliberate, skips two-arm gaps, consistent with the spec's accepted regression discontinuity. - **`green/applicable` denominator in the readout** — deliberate, reads more honestly than counting unscoreable two-arm runs against the total. - **Faint dashed zero baseline in the sparkline** — a readability aid not requested by the spec, harmless.
alexion added 1 commit 2026-07-24 16:38:29 -04:00
Add the longitudinal layer to the benchmark core: a per-skill JSON-lines
history that appends one summary line per run and trims oldest-first at
fifty, two stacked net-margin trend ribbons (Efficacy and Regression, the
latter leaving a gap for two-arm runs) with the current run ringed and a
net/delta/green-count readout, and per-badge fragility chips that flag the
narrowest passing case on each green axis so a barely-green skill cannot
look robust.

History persistence is opt-in via --history and is the core's only side
effect. Without it the core stays a pure transform. Two committed fixtures
(clean and fragile) and new fixture-test sections cover the append-and-trim,
both ribbons including the two-arm gap, and the chips.
alexion merged commit f4df5d31c9 into main 2026-07-24 16:41:33 -04:00
alexion deleted branch task-0006-trend-history-and-ribbons 2026-07-24 16:41:33 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alexion/skills#6