Notice when a Mech card drifts from the site it cites - #109
Merged
Merged
Conversation
This was referenced Sep 22, 2026
Closed
Closed
The card headline figures are hand-curated from each Mech's published browser. Nothing regenerates them and nothing noticed when they went stale, so the only thing standing between the page and a wrong number was somebody looking (#104). Four of ten have drifted since the last refresh two days ago: CommunityMech card 392 site 405 CultureMech card 6,286 site 6,288 MediaIngredientMech card 2,951 site 2,952 TraitMech card 723 site 751 I had found two of those by hand; the check found four, which is the argument for having it. Scheduled only, and deliberately not on pull_request. The ten sites publish on their own cadence — TraitMech moved again while this was being written — so a blocking check would make an unrelated docs fix unmergeable whenever a Mech shipped records overnight. The nightly cron already exists; a red there is actionable, a blocked PR is not. The ten do not agree on how they publish the figure, so SOURCES pins it per Mech rather than guessing: a stat tile for six, prose for CultureMech and NaturalProductMech, and a JSON file for ProteinTraitsMech and MediaIngredientMech, whose pages compute it at runtime and whose markup carries only a placeholder. CultureMech points at pages/ rather than the app/ landing tile, which is the legacy figure matching no data layer. All of these are the pages/ or app/ URL, never the repo root, since several roots are client-side meta-refresh shells that return 200. A fetch that does not arrive is a warning; a fetch that arrives and does not match is a failure. Conflating them would teach people to ignore a nightly red for somebody else's outage — and the distinction earned itself immediately, reporting "shape changed" for the two prose sites rather than inventing drift, which is how the prose kind came to exist. A test pins that every card has an entry in SOURCES and vice versa, so an eleventh Mech cannot get a card and be silently exempt. Verified it fails by removing TaxonMech from the table. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
From the adversarial review of this PR. published() reached for document.get() before checking the shape, so a body that is a bare JSON list raised AttributeError, which the except clause did not name; the nightly run died with a traceback instead of an "unread" line, and the list fallback below it was unreachable (closes #110). The shape is tested first now, and a body of an unexpected type is reported, not raised. _fleet/README.md enumerates the pipeline scripts and the hand-curated card layer but said nothing about the check; it now says what it compares, when it runs and why a nightly red is not a PR red (closes #111). The review skill's gate section said the workflow runs exactly three things; it now separates the three merge-blocking steps from the scheduled card check (closes #112). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
realmarcin
force-pushed
the
feat/card-drift-check
branch
from
September 22, 2026 07:28
e188035 to
d6eb8ca
Compare
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.
Closes #104.
The card headline figures are hand-curated from each Mech's published browser. Nothing regenerates them, and nothing noticed when they went stale.
It found twice what I found by hand
The triage sweep caught CommunityMech and TraitMech. The check caught four — including CultureMech, whose canonical count moved, and which I would not have thought to re-check.
Scheduled only, not on
pull_requestThe nightly cron already exists. A blocking check would make an unrelated docs fix unmergeable whenever a Mech shipped records overnight — TraitMech went 750 → 751 while this PR was being written. Nightly red is actionable; a blocked PR is not.
The ten sites do not agree on how they publish it
SOURCESpins it per Mech rather than guessing:htmltextjsonCultureMech points at
pages/, not theapp/landing tile — that one is the legacy figure matching no data layer. All arepages/orapp/URLs, never the repo root, since several roots are meta-refresh shells returning 200.A fetch that fails is not a number that is wrong
Warning for the first, failure for the second. Conflating them teaches people to ignore a nightly red for someone else's outage.
The distinction earned itself immediately: the first run reported "html shape changed" for CultureMech and NaturalProductMech rather than inventing drift — which is how the
textkind came to exist. A checker that had guessed would have reported two false drifts and hidden two real ones.Coverage is pinned
A test asserts every card has a
SOURCESentry and vice versa, so an eleventh Mech cannot get a card and be silently exempt — which is this issue's failure mode one level up. Verified it fails by removing TaxonMech from the table.29 tests pass,
assemble_page.py --checkclean, workflow YAML parses with the new step correctly gated.Not fixed here: the four drifted figures. Refreshing them belongs with #84/#87's full pipeline run, where the card and graph sources are updated together.
Review fixes
Rebased over #108. From the adversarial review, fixed here: a bare-list JSON body crashed
published()with an uncaughtAttributeErrorinstead of being reported unreadable, and the list fallback was unreachable (closes #110);_fleet/README.mdnow documents the check (closes #111); the review skill's gate section separates the three merge-blocking steps from the scheduled card check (closes #112). Left filed: #113 (five cards now drift, nightly will be red until the #84/#87 refresh), #114 (three card regexes), #115 (all-unreadable run exits 0).🤖 Generated with Claude Code