Skip to content

Give trait pages their own stamp instead of the corpus-wide one (#304) - #340

Merged
realmarcin merged 1 commit into
mainfrom
fix/304-corpus-footer
Aug 6, 2026
Merged

Give trait pages their own stamp instead of the corpus-wide one (#304)#340
realmarcin merged 1 commit into
mainfrom
fix/304-corpus-footer

Conversation

@realmarcin

Copy link
Copy Markdown
Contributor

The corpus-as-of stamp is the maximum curation_history timestamp across the whole
corpus
, inlined into every page. Because the value is global but stored per-page, any
PR appending a curation event — i.e. every data PR, since the playbook requires one —
rewrote all 477 trait pages.

PR #300 changed 14 trait files and produced a 508-file diff, 477 of them nothing but a
footer timestamp. #339, earlier in this same session, touched 495 files for one curation
event
— so this is a live tax, not a hypothetical one.

The fix

Took the issue's option 1 — store the value once rather than 477 times — but without
dropping it from trait pages. They now carry their own latest curation timestamp:

Record as of 2026-08-06 07:00 UTC from METPO ...

That changes only when the record changes, and "when was this trait last curated" is
the more useful question on a trait page anyway. The corpus-wide stamp stays on the
aggregate pages (browse, category, umap, graph), where it's a property of what's being shown.

Measured, not asserted

Appending one curation event to one record and re-rendering:

pages rewritten
before 477+
after 13

The 13 are the changed trait page, browse, graph, umap, and the 9 category pages —
all of which legitimately carry the corpus stamp.

The changed trait page IS among the 13, checked explicitly. A "fix" that stopped the
real page from changing would be worse than the churn it removed.

Trait pages now show 29 distinct record stamps where there was previously 1 global value.

Notes

  • pages/index.html carries no stamp either way — its template doesn't extend base.html.
    Pre-existing; verified against main, not touched here.
  • Three tests pin the distinction, including that a record's stamp is not the corpus
    maximum — the property the whole change rests on.

just qc green (including OK pages/) · 434 tests pass · ruff clean.

Closes #304.

🤖 Generated with Claude Code

The corpus-as-of stamp is the maximum curation_history timestamp across
the whole corpus, inlined into every rendered page. Because the value is
global but stored per-page, ANY PR appending a curation event -- i.e.
every data PR, since the playbook requires one -- rewrote all 477 trait
pages. PR #300 changed 14 trait files and produced a 508-file diff of
which 477 were nothing but a footer timestamp; #339 in this same session
touched 495 files for one curation event.

Took the issue's option 1, storing the value once rather than 477 times,
but without dropping it from trait pages: they now carry their OWN
latest curation timestamp, labelled "Record as of". That changes only
when the record changes, and "when was THIS trait last curated" is the
more useful question on a trait page anyway. The corpus-wide stamp stays
on the aggregate pages, where it is a property of what is being shown.

Measured, not asserted. Appending one curation event to one record and
re-rendering:

  before: 477+ pages rewritten
  after:  13 -- the changed trait page, browse, graph, umap, and the 9
          category pages, all of which legitimately carry the corpus stamp

The changed trait page IS among the 13, checked explicitly; a fix that
stopped the real page changing would be worse than the churn.

pages/index.html carries no stamp either way -- its template does not
extend base.html. Pre-existing, verified against main, not touched here.

Three tests pin the distinction, including that a record's stamp is not
the corpus maximum, which is the property the whole change rests on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@culturebot-reviewer

culturebot-reviewer Bot commented Aug 6, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 2m 44s —— View job


Review: approved ✅

  • Read repo conventions (README / docs)
  • Review scripts/render_trait_pages.py + base.html
  • Review tests
  • Verify the churn-reduction claims against the tree
  • Post verdict — approved

No 🔴 or 🟡. No data/traits/**, ontology CURIEs, evidence snippets, or causal-graph edges are touched, so the data-integrity surface is untouched; no history/ record is needed for a tooling change.

What I checked, rather than took on faith:

  • All 477 trait pages carry exactly one Record as of … stamp — none regressed to the Built from fallback, i.e. every record has a parsable curation_history.
  • The aggregate pages (browse, graph, umap, category/*) are absent from the diff and still carry the corpus stamp — the two scopes are consistent, not accidentally diverged.
  • Nothing outside src/traitmech/templates/base.html:38 reads the footer string (checked scripts/, tests/, justfile, docs/, .github/), so no staleness gate or CI script depends on Corpus as of being the literal text.
  • {{ stamp_scope | default('Corpus') }} is correct for the aggregate calls that don't pass it — Jinja's default handles the undefined case even under strict undefined.

🔵 Suggestions (all optional)

1. Duplicated "latest of curation_history" rule. record_timestamp (scripts/render_trait_pages.py:154) is a verbatim copy of corpus_timestamp's inner loop, including the _as_utc skip and the strftime format. Two copies of one rule can drift. corpus_timestamp could be max over per-record values via a shared _latest(entries) helper. Fix this →

2. Stale comment. scripts/render_trait_pages.py:330 still reads "One value for every page in the run, derived from the data (#228)". That is exactly what this PR stops being true. Fix this →

3. The footer still mixes scopes. A trait page now reads Record as of 2026-07-20 04:23 UTC … · 477 TraitRecords · embedding coverage 100.0% — the date is record-scoped, the two figures beside it are corpus-scoped. So adding or removing a trait still rewrites all 477 pages. That's outside #304, which is scoped to the curation timestamp, and far rarer than a curation event — not a defect here. Worth knowing only because the before/after measurement in the description covers curation events and not this path.

Minor: the three new tests would sit naturally in the existing tests/test_render_trait_pages.py, which already carries the same sys.path bootstrap; a second module for one function is a small amount of duplicated scaffolding.
· fix/304-corpus-footer

@culturebot-reviewer culturebot-reviewer Bot 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.

No blocking issues. The change is correct and well-scoped: no data/traits/**, no ontology CURIEs, no evidence snippets touched, so the data-integrity surface is untouched. I verified the mechanical claims — all 477 trait pages carry exactly one Record as of stamp (none regressed to the Built from fallback), the aggregate pages are unchanged and still carry the corpus stamp, and nothing outside base.html:38 parses the footer string.

Three optional notes:

Duplicated "latest of curation_history" rule. record_timestamp is a verbatim copy of corpus_timestamp's inner loop. Two copies of the same rule can drift — corpus_timestamp could be max over per-record values via a shared _latest(entries) helper.

Stale comment. scripts/render_trait_pages.py:330 still says "One value for every page in the run, derived from the data (#228)". That is no longer true for trait pages.

The footer still mixes scopes. A trait page now reads Record as of 2026-07-20 04:23 UTC ... · 477 TraitRecords · embedding coverage 100.0% — the date is record-scoped, the two counts are corpus-scoped. Adding or removing a trait still rewrites all 477 pages. That's outside #304's scope (which is specifically the curation timestamp) and much rarer than a curation event, so it isn't a defect in this PR — but it is the same class of problem and worth knowing the measurement didn't cover it.

@realmarcin
realmarcin merged commit b32bd3d into main Aug 6, 2026
5 checks passed
@realmarcin
realmarcin deleted the fix/304-corpus-footer branch August 6, 2026 09:32
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.

The corpus-as-of footer is inlined into all 477 pages, so any curation_history change rewrites every one

1 participant