Skip to content

Report review and pull-request counts, light the graph nodes, move the heatmap up - #77

Merged
realmarcin merged 2 commits into
mainfrom
feat/mech-pr-and-review-stats
Sep 16, 2026
Merged

realmarcin merged 2 commits into
mainfrom
feat/mech-pr-and-review-stats

Conversation

@realmarcin

Copy link
Copy Markdown
Contributor

Replaces #63, which GitHub closed automatically when its base branch was deleted on merging #60. Rebuilt onto main after #71 and #72 landed, which replaced the assembler with a manifest-driven one, added a test suite and a CI check, and took the fleet to ten members.

Two pieces of the original branch were superseded by that work and are dropped: main already derives the graph's accessible title from the fleet count, and already gives NaturalProductMech its Browse button.

Merged pull requests, on the strip and on every card. A fifth tile carries 2,778 merged PRs across the ten Mech repositories, and each card gains small print under its headline number.

Mech reviewed merged PRs
TaxonMech 0 15
NaturalProductMech 0 80
HabitatMech 684 130
AntibioticMech 80 160
ProteinTraitsMech 39,591 314
MediaIngredientMech not tracked 359
CellStructureMech 0 425
TraitMech 427 517
CommunityMech not tracked 528
CultureMech not tracked 250

Where "reviewed" comes from. Each Mech's LinkML schema, not the values its records happen to carry. Seven declare a status slot whose enum permits REVIEWED, so a zero there is a real zero. MediaIngredientMech and CultureMech have a mapping_status, but its enum runs UNMAPPED to AMBIGUOUS and never reaches REVIEWED, so it grades mapping rather than review; CommunityMech has no such slot. Those three print only their PR count, because "nobody has reviewed one" and "this Mech does not track review" are different claims.

Fits the manifest contract main introduced. mech_stats.py takes membership from the manifest snapshot, the same source assemble_page.py validates the cards against, so a Mech admitted to the fleet cannot end up with a card and no stat line. roots.ORDER stays at nine, because it is a narrower thing: the members the vocabulary scans have measured. TaxonMech's record glob lives in mech_stats.py until the census reaches it. assemble() refuses to build if the stats miss a member, and two new tests cover that and the untracked-review case.

The heatmap moves above the graph, from the template into the fragment, since the graph is what it explains. Its heading is raw HTML carrying the id kramdown would have generated, because markdown is not processed inside the fragment.

Graph nodes are lit as spheres. One highlight gradient and one limb gradient, both in objectBoundingBox units so a single pair serves all ten, neither carrying a hue, both multiplying over whichever Mech colour is underneath. The weighting is a theme token because it has to change: light-theme Mech colours are far darker, since they carry their contrast against white, and a limb tuned for the dark theme turned them to mud. The overlay circles take no pointer events, so hovering still hits the node. The hub keeps its flat fill and reads as the centre rather than an eleventh planet.

Layout. The stat strip steps 5 to 3 to 2 columns on explicit breakpoints. auto-fit picks four between roughly 700px and 1010px, which strands the fifth tile alone on a stretched row.

Checks: python -m unittest discover -s tests passes 13 tests, and python scripts/fleet/assemble_page.py --check reports the page current. Verified in Chrome against a local render at 1400px: five tiles on one row, ten shaded nodes, ten card stat lines, heatmap ahead of the graph with no horizontal overflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BXHrBTSU8fU4Zg7HfaMKs9

…e heatmap up

Rebuilt onto main after #71 and #72 landed, which replaced the assembler with
a manifest-driven one, added a test suite and a CI check, and took the fleet to
ten members. Two pieces of the original branch were superseded and are dropped:
main already derives the graph's accessible title from the fleet count, and
already gives NaturalProductMech its Browse button.

A fifth stat tile carries merged pull requests summed across the ten Mech
repositories, and every card gains a line of small print under its headline
number with that Mech's reviewed records and merged PRs.

Whether a Mech tracks review is read from its LinkML schema, not from the
values its records happen to carry. Seven declare a status slot whose enum
permits REVIEWED, so a zero there is a real zero. MediaIngredientMech and
CultureMech have a mapping_status, but its enum runs UNMAPPED to AMBIGUOUS and
never reaches REVIEWED, so it grades mapping rather than review; CommunityMech
has no such slot. Those three print only their PR count, because "nobody has
reviewed one" and "this Mech does not track review" are different claims.

mech_stats.py takes fleet membership from the manifest snapshot, the same
source assemble_page.py validates the cards against, so a Mech admitted to the
fleet cannot end up with a card and no stat line. roots.ORDER is a narrower
thing, the members the vocabulary scans have measured, and stays at nine.
TaxonMech's record glob lives in mech_stats.py until the census reaches it.
assemble() now refuses to build if the stats miss a member, and two tests cover
that and the untracked-review case.

The Shared vocabulary heatmap moves above the graph, from the template into the
fragment, since the graph is what it explains. Its heading is raw HTML carrying
the id kramdown would have generated, because markdown is not processed inside
the fragment.

Graph nodes are lit as spheres: one highlight gradient and one limb gradient,
both in objectBoundingBox units so a single pair serves all ten, neither
carrying a hue, both multiplying over whichever Mech colour is underneath. The
weighting is a theme token because it has to change -- light-theme Mech colours
are far darker, carrying their contrast against white, and a limb tuned for the
dark theme turned them to mud. The overlays take no pointer events, so hovering
still hits the node. The hub keeps its flat fill and reads as the centre.

The stat strip steps 5 to 3 to 2 columns on explicit breakpoints; auto-fit
picks four between roughly 700px and 1010px and strands the fifth tile alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BXHrBTSU8fU4Zg7HfaMKs9
Copilot AI lite review requested due to automatic review settings September 16, 2026 17:30

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Review of this branch measured what the highlight costs in colour separation.
It lightens the middle of every node toward white, which pulls the ten Mech
colours together: at the peak as submitted, the closest dark-theme pair fell
from 0.106 to 0.054 in linear-RGB distance, and the worst pair overall held
only 57% of its flat separation. The pair it hurt most was the one already too
close to tell apart, CellStructureMech and TaxonMech (#78).

Dropped from .52 to .34 on dark and .60 to .42 on light. The dark theme keeps
77% of flat separation and still reads as a lit sphere, because the limb
shadow does most of the modelling there by design. The light theme leans on
the highlight instead, so it keeps more of it. Checked in both themes.

Closes #79

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BXHrBTSU8fU4Zg7HfaMKs9
@realmarcin

Copy link
Copy Markdown
Contributor Author

Adversarial review done, read-only, against main. Findings filed as #78 and #79.

What I checked beyond reading the diff:

  • Ran main's own gates, which did not exist when this work started: 13 tests pass and assemble_page.py --check reports the page current. Two of those tests are new here, covering a Mech in the manifest with no stat entry, and the untracked-review case.
  • Confirmed mech_stats.py now covers all ten members, including TaxonMech, whose corpus under data/taxa/**/*.yaml is 625,960 files and matches its card exactly.
  • Measured what the sphere shading costs in colour separation, as linear-RGB distance between each pair of node colours before and after lighting. That is what turned up both findings.
  • Checked both themes in Chrome at 1400px.

Addressed here: #79, a real defect in this branch. The highlight washes every node toward white, which pulls the ten Mech colours together. At the peak as submitted the worst dark-theme pair held only 57% of its flat separation. Lowered from .52 to .34 on dark and .60 to .42 on light, which restores 77% while still reading as a lit sphere, since the limb shadow does most of the modelling on dark by design.

Left filed: #78, and it is the more serious of the two. CellStructureMech and TaxonMech are byte-identical on the light theme, both #5257C9, and all but identical on dark. Those colours are each Mech's identity across the ring, the card spines and the heatmap row dots, so on the light theme two Mechs currently carry no distinction at all. It predates this PR and this PR has no business picking replacement brand colours; the token comment already notes that the original eight filled the hue circle at that lightness, so a ninth and tenth need deliberate treatment checked in both themes and for colour-vision deficiency.

Also noted while reading: NaturalProductMech moved into the blue family in the same earlier change, which now puts three of ten in blue.

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