Skip to content

Render the research block by looking for the file the pipeline writes (#233) - #253

Merged
realmarcin merged 4 commits into
mainfrom
fix/render-research-filename
Aug 5, 2026
Merged

Render the research block by looking for the file the pipeline writes (#233)#253
realmarcin merged 4 commits into
mainfrom
fix/render-research-filename

Conversation

@realmarcin

Copy link
Copy Markdown
Contributor

Closes #233. Resolves the tie-break half of #245.

render_trait_pages.py:286 looked for research/traits/<cat>/<slug>.md. The pipeline writes <slug>-deep-research-<provider>.md — the suffix is load-bearing, since sweep resume detection is file-existence based on that exact name. So research_md was always empty, and both the <pre class="research-md"> block in trait.html and its CSS rule were dead code. 353 reports in the tree, not one rendered.

Four decisions, not one lookup fix

Provider precedence, not alphabetical order

#233 proposed "sorting by name and taking the first." Exactly one trait has two providers — cellulolysis, with -falcon and -codex — and name order picks codex, the single artifact in the tree with no manifest row and no citations sidecar (#245). So the one trait where the tie-break fires is the one that would render an unrecorded artifact.

Ranked by known provider instead, with name order as the fallback so an unrecognised provider still renders reproducibly rather than by directory iteration order (#228).

Preview, not full embed

Embedding whole reports takes pages/ from 16 MB to 31 MBmutualism.html 36 KB → 80 KB — to store a second copy of text that #240/#241 already track, and turns every future sweep into a 353-file diff against the staleness gate.

The card is a scrolling 480px-tall <pre>, so a reader was never going to consume a 30 KB report on the page; they were going to open the file. 60 lines plus a link costs 3 MB instead of 15. RESEARCH_PREVIEW_LINES is one constant if that trade is ever judged the wrong way round.

The preview has to skip the prompt

The provider echoes the entire rendered template twice before answering, so a head-of-file preview shows YAML front matter, template_file: /Users/marcin/..., and the prompt — and zero findings. research_answer() trims the front matter and everything through the prompt's last line, a marker present exactly twice in all 353 reports, and degrades gracefully for a layout without it. A test asserts every one of the 354 tracked reports still yields a substantial body after the trim.

The gate's guard is inverted, not deleted

audit-derived-reports rejected any research block, because the renderer read a gitignored directory: a committed research-bearing page could not be reproduced by CI and would wedge the gate permanently. #230 listed three ways out — stop committing such pages, exclude the block from the comparison, or track the inputs. #240/#241 took the third, which is what makes this issue fixable at all.

So the collision is gone and only its precondition remains. The guard now fires when a block is rendered and research/traits is untracked — the same divergence, surfaced as a cause rather than as an unexplained 353-file STALE. Both branches canaried: it fires against a simulated untracked path, and stays silent when no block is rendered.

Labelled for what it is

Rendering turns a hedged research note into page content, which is the concern raised against #243. The block now carries a warning — styled as one, not as more grey metadata — that this is unreviewed provider output whose suggested identifiers have not been resolved and are known in places to be wrong.

Verification

353 research blocks rendered   (0 before)
cellulolysis renders           -falcon, not -codex
pages/                         16 MB → 19 MB
tests                          269 pass (13 new)
just qc                        exit 0

The pages/ diff is 353 trait pages plus assets/style.css.

Not addressed here

#243 remains the substantive open question about this corpus: roughly 80-100 of the suggested CURIEs are wrong. The warning above makes that visible to a reader; it does not fix the data. #245's other half — whether the codex artifact should exist at all — is still a decision, though this PR removes its ability to surface on a page.

🤖 Generated with Claude Code

…#233)

render_trait_pages.py looked for `research/traits/<cat>/<slug>.md`. The
pipeline — and the deep-research-trait skill — write
`<slug>-deep-research-<provider>.md`; the suffix is load-bearing, since sweep
resume detection is file-existence based on that exact name. So `research_md`
was always empty, and the <pre class="research-md"> block in trait.html and its
CSS rule were both dead code. 353 reports, not one rendered.

Now globs what the pipeline writes and ranks by provider. Ranking, not sorting:
`cellulolysis` is the one trait with two providers, and alphabetical order picks
`-codex` — the single artifact in the tree with no manifest row and no citations
sidecar (#245). Unknown providers still fall back to name order, so an
unrecognised provider renders reproducibly rather than by directory order
(#228).

Previews rather than embeds. A full embed takes pages/ from 16 MB to 31 MB —
mutualism.html 36 KB → 80 KB — to store a second copy of text that #240/#241
already track, and makes every future sweep a 353-file diff against the
staleness gate. The card is a scrolling 480px <pre>, so nobody was reading a
30 KB report on the page anyway. 60 lines plus a link costs 3 MB.

Those 60 lines have to be the answer. The provider echoes the whole rendered
prompt twice before responding, so a head-of-file preview shows YAML front
matter and the prompt and zero findings. research_answer() trims front matter
and everything through the prompt's last line — a marker present exactly twice
in all 353 reports — and falls back gracefully for a layout that lacks it.

The staleness gate's research guard is inverted rather than deleted. It
rejected any research block because research/ was gitignored, and named the
three ways out; #240/#241 took "track the inputs", so the collision is gone.
What remains is its precondition, so the guard now fires when a block is
rendered and research/traits is NOT tracked — the same divergence, reported as
a cause instead of an unexplained 353-file STALE. Both branches canaried.

The block is labelled for what it is: unreviewed provider output whose
suggested CURIEs are measurably unreliable (#243), styled as a warning rather
than as more grey metadata.

353 blocks now render. 269 tests pass, `just qc` exits 0.

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

culturebot-reviewer Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 4m 30s —— View job


Review

The lookup fix is right and the reasoning behind each of the four decisions holds up — I checked the load-bearing claims against the tree rather than taking the body's word for them:

  • cellulolysis renders -falcon (pages/traits/metabolism/cellulolysis.html:478), not the manifest-less -codex. ✅
  • The prompt marker appears exactly twice in all 353 marker-bearing reports — I counted. The 354th (cellulolysis-deep-research-codex.md) has a different layout with no front matter and no marker, so it takes the documented fallback; it is never selected anyway. The arithmetic in the body checks out. ✅
  • 353 pages carry a block; git diff --stat on pages/ is 354 files (353 + style.css). ✅
  • select_autoescape(["html"]) is on (render_trait_pages.py:288), so provider markdown in <pre> is escaped. ✅
  • The glob is prefix-safe (biosafety_level doesn't capture biosafety_level_2) and sidecars are excluded — both pinned by tests.

tests/test_render_research_lookup.py is good work. test_every_tracked_report_yields_a_substantial_answer is the right shape: it ratchets on the real corpus, so a future sweep whose layout breaks the trim fails the suite instead of silently emptying 353 pages.

Two things.


🟡 The caveat does not read as a warning, and this stylesheet already has one that does

style.css:179-189. The comment above the rule states the requirement plainly — "the caveat has to read as a warning rather than as more grey metadata." The rule then sets background: var(--accent-soft) with no border and no lead-in.

--accent-soft is #F7CDCD, which on the very same page is also the background for table.trait-list th, table.trait-list tr:hover, .nn-list .nn-cat, and .research-card itself (:149). So the caveat is tinted the same as ordinary chrome. It isn't grey — but it isn't distinguishable from decoration either, which is the property that mattered.

Meanwhile .graph-warning (:194-204) is fifteen lines below: amber #fff7ed / #fdba74 / #9a3412, a real border, a <strong> lead-in, and dark-mode overrides at :450 and :464. It is already used in this same template (trait.html:26) for graph integrity warnings. .research-caveat ships no dark-mode rule at all, so in dark mode it falls to --accent-soft: #2a1e1f — readable, but flat.

This matters more than a styling nit because it is the whole mitigation. The PR's case for rendering a corpus in which ~80-100 suggested CURIEs are wrong (#243) rests on a reader seeing that warning; docs/GROUNDING_POLICY.md documents how badly this corpus's identifiers have gone wrong before (99 of 138 UniProt accessions inactive). Reusing .graph-warning gets the established idiom and both themes for free.

Fix this →


🔵 The guard's premise is coarser than the divergence it describes

justfile:506-507 fires only when research/traits is untracked entirely — one tracked file satisfies git ls-files research/traits | head -1. With 353 committed, that condition is now effectively unreachable.

The narrower case survives: a curator runs a new sweep, renders, and commits pages/ without committing the new report. Locally just qc passes — render matches pages/. In CI the fresh render has no block for that trait, pages/ does, and the result is a STALE with the guard silent — the "unexplained STALE rather than a cause" outcome the comment says it is preventing, reached via an untracked file instead of an untracked directory.

Narrow, and not corrupting — the gate still fails, it just fails uninformatively. Checking that the reports the renderer actually picked are tracked (rather than that the directory is non-empty) would close it. Your call whether it's worth the line.


Nothing else. No data/traits/** changes, so no history/ record is expected and the ontology/evidence/causal-graph surface is untouched — this is a rendering change and I reviewed it as one. The preview cutting mid-list is fine given the "first 60 of 240" footer.

Note on verification: I could not execute pytest or just qc — command execution is sandboxed in this environment, so the 269-pass / exit-0 claims are unverified by me. Everything else above I confirmed by direct inspection of the tree.

Requesting changes on the caveat styling alone; the 🔵 is optional.

· branch fix/render-research-filename

@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.

The lookup fix is right and the four decisions hold up — I verified the load-bearing claims against the tree: cellulolysis renders -falcon, the prompt marker appears exactly twice in all 353 marker-bearing reports (the 354th, the codex artifact, has no marker and takes the documented fallback), 353 blocks render, and autoescape is on so provider markdown in

 is escaped. test_every_tracked_report_yields_a_substantial_answer is the right ratchet.

One blocking item.

🟡 style.css:179-189 — the .research-caveat rule sets background: var(--accent-soft), which on the same page is also the background for table headers, hover rows, .nn-cat chips, and .research-card itself. So the caveat is tinted like ordinary chrome, contradicting its own comment ('has to read as a warning rather than as more grey metadata'). Fifteen lines below, .graph-warning (:194-204) is the established warning idiom in this very stylesheet — amber, bordered, with a lead-in and dark-mode overrides at :450 and :464 — and it is already used in this template at trait.html:26. .research-caveat has no dark-mode rule at all.

This matters because it is the entire mitigation. The case for rendering a corpus in which ~80-100 suggested CURIEs are wrong (#243) rests on the reader seeing a warning, and GROUNDING_POLICY.md documents how badly this corpus's identifiers have gone wrong before. Reusing .graph-warning gets the idiom and both themes for free.

🔵 Optional: justfile:506 fires only when research/traits is untracked entirely, which one tracked file defeats. A curator who commits pages/ without committing a new report still produces an unexplained CI STALE with the guard silent — the same outcome the comment says it prevents, via an untracked file rather than an untracked directory. Checking that the picked reports are tracked would close it.

No data/traits changes, so no history/ record is expected and the ontology/evidence/graph surface is untouched. Note that I could not execute pytest or just qc in this environment, so the 269-pass and exit-0 claims are unverified by me; everything else I confirmed by inspection.

…case

Four review findings.

The caveat was tinted with --accent-soft, which on the same page is already
the background of table headers, hover rows, .nn-list chips and .research-card
itself — so the thing that had to read as a warning read as decoration, and it
shipped no dark-mode rule. It now reuses .graph-warning: the established
warning idiom on this template, with a border, a strong lead-in, and overrides
in both theme branches. That mattered more than styling usually does, since the
warning is the whole mitigation for rendering a corpus with ~80-100 wrong
CURIEs (#243). (#256)

The line count said "the first 60 of 255 lines" and linked a 417-line file. The
count described the trimmed answer, the link the whole report. Now says which
it counts and what else the file holds. (#254)

research_answer() anchored on the LAST prompt marker. Identical today — the
marker appears exactly twice in all 353 reports — but the failure modes are
asymmetric: an answer quoting the instruction line, which these reports
plausibly do, would be cut mid-answer and silently lose findings, whereas
overshooting only leaves boilerplate in the preview. Now anchors on the second,
with a test for the quoted-marker case and one asserting the twice-exactly shape
the trim depends on, so a layout change fails loudly. (#255)

The pages guard tested whether research/traits was tracked at all, which 353
committed reports made unreachable. The reachable divergence is narrower: a
curator generates a report, renders, commits pages/ but not the report — qc
passes locally, CI renders no block, STALE with the guard silent. It now
reports that case separately, names the offending files, and prints the git add
that fixes it. Canaried: firing on an uncommitted report names it exactly.

271 tests pass, `just qc` exits 0.

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

culturebot-reviewer Bot commented Aug 4, 2026

Copy link
Copy Markdown

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


Review

  • Read repo conventions (README, docs/)
  • Check the caveat restyle (🟡 from last round)
  • Check the justfile guard rework (🔵 from last round)
  • Check the marker-anchoring change (second vs last) and its tests
  • Check the line-count wording fix
  • Verify the regenerated pages/ matches the templates
  • Post verdict — approved

The blocking item is resolved and the three follow-ons landed cleanly.

The caveat now reads as a warning. trait.html:227 reuses .graph-warning instead of a bespoke --accent-soft tint, so it inherits the border, the strong { display: block } lead-in, and dark-mode overrides in both theme branches (style.css:445, :459). The comment left at style.css:179-184 explains why there is no rule there — the right thing to leave behind, since the next person to add a research style would otherwise re-derive the same mistake. Verified in the regenerated output:

check result
pages with a research block 353
pages with the warning 353
src/…/style.css vs pages/assets/style.css byte-identical
leftover .research-caveat references none

The line count now says which count it is. "Showing the first 60 of 240 lines of findings; the linked file also carries the run's front matter and the prompt it was given" (cellulolysis.html:546). Accurate on both halves.

The marker anchoring moved to the second occurrence, with the asymmetry argued inline: overshooting leaves boilerplate in the preview, undershooting silently drops findings. test_a_quoted_marker_in_the_answer_does_not_truncate_it pins the case that motivated the change, and test_the_prompt_marker_appears_exactly_twice_in_every_sweep_report asserts the shape the trim depends on — so a future provider layout fails loudly instead of quietly moving the boundary. That is the better of the two tests to have added.


🔵 The guard swapped under-firing for over-firing

justfile:512. The outer condition is now always true — 353 blocks always render — so the check reduces to "any untracked, non-ignored file under research/traits fails qc", which is broader than the divergence the comment above it describes. An untracked .citations.md sidecar, a report for a provider research_report() did not pick (a second -codex, say), or simply a sweep still in progress will trip it and report "a research block is rendered from reports that are not committed" about a file with no bearing on the render.

Given that 342 reports were lost to precisely this failure (.gitignore:41), erring toward commit your research output is defensible policy — it is only the message that overclaims. Checking the reports research_report() actually selects would make the message true. Not requesting it.


No data/traits/** changes, so no history/ record is expected and the ontology / evidence / causal-graph surface is untouched.

Note on verification: pytest and just qc are not executable in this environment, so the 271-pass and exit-0 claims remain unverified by me. Everything above I confirmed by inspecting the tree and the regenerated pages.

· branch fix/render-research-filename ·

@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.

The blocking item is resolved and the three follow-ons landed cleanly.

The caveat now reuses .graph-warning (trait.html:227) instead of a bespoke --accent-soft tint, so it inherits the border, the strong { display: block } lead-in, and dark-mode overrides in both theme branches (style.css:445, :459). The comment left behind in style.css:179-184 explains why there is no rule there, which is the right thing to leave. Verified in the regenerated output: 353 pages carry a block and all 353 carry the warning; src and pages/assets/style.css are byte-identical.

The line-count wording now says which count it is reporting and what else the linked file holds ("the first 60 of 240 lines of findings; the linked file also carries the run's front matter and the prompt"). Accurate.

research_answer() anchoring moved from the last marker to the second, with the reasoning inline. The asymmetry argument is right — overshooting leaves boilerplate, undershooting silently drops findings — and test_a_quoted_marker_in_the_answer_does_not_truncate_it pins the case that motivated it, alongside a test asserting the exactly-twice shape the trim depends on, so a layout change fails loudly rather than quietly moving the boundary.

One 🔵, no change requested. The guard's outer condition (justfile:512) is now always true — 353 blocks always render — so the check reduces to "any untracked, non-ignored file under research/traits fails qc", which is broader than the divergence the comment describes. An untracked sidecar, a report for a provider the renderer did not pick, or a sweep still in progress trips it and reports "a research block is rendered from reports that are not committed" about a file with no bearing on the render. Given that 342 reports were lost to exactly this (.gitignore:41), erring toward "commit your research output" is defensible; only the message overclaims. Checking the reports research_report() actually picks would make the message true.

No data/traits changes, so no history/ record is expected and the ontology/evidence/causal-graph surface is untouched.

Note: pytest and just qc are not executable in this environment, so the 271-pass / exit-0 claims remain unverified by me. Everything above I confirmed by inspecting the tree and the regenerated pages.

The #257 fix over-corrected. With 353 blocks always rendering, the outer
condition is always true, so the check had become "any untracked file under
research/traits fails qc" — and it said, of each one, that a research block was
rendered from it. Not true of a `.citations.md` sidecar, which
research_report() explicitly excludes.

Now checks only `*-deep-research-*.md` minus sidecars: exactly the candidate set
research_report() selects from. The message drops from "CI cannot reproduce it"
to "CI may not reproduce this render", since a candidate only changes the output
if it wins the provider ranking.

Still strict about in-progress sweeps, deliberately — 342 reports were lost to
the opposite instinct. The defect was the claim, not the strictness.

Canaried in three states: untracked sidecar passes, untracked report fails
naming the file, clean tree passes. 271 tests pass, `just qc` exits 0.

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

culturebot-reviewer Bot commented Aug 4, 2026

Copy link
Copy Markdown

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


Review

The only change since the last approval is the guard narrowing, and it lands correctly. The claim it rests on — that -deep-research- minus .citations.md is the set research_report() selects from — I checked rather than took on faith:

  • All 707 tracked files under research/traits are .md: 354 reports and 353 sidecars. No .json/.yaml provenance in that namespace, so nothing untracked there can trip the guard and be described wrongly.
  • The other capture path can't contribute one either. _edison_capture.capture_full_response writes {stem}-meta.yaml, -response.json, -citations.md, -agent-state.json — but research_trait_edison.py:212 builds stem = f"{slug}-edison-{job_short}…", so none of it carries -deep-research-. The two namespaces don't overlap.
  • set -euo pipefail is on (justfile:379), so the || true on the new pipeline is load-bearing, not decoration — grep exiting 1 on no match, and head -3 SIGPIPE-ing its upstream, would both abort the recipe without it. It's there.
  • Message wording matches what the check can actually prove: "may not reproduce" rather than "cannot", since an untracked candidate only changes output if it wins the ranking. That was the whole defect from last round, and it's the part that got fixed.

Still verified from the previous round: 353 pages carry a block, all 353 carry the warning, src/…/style.css and pages/assets/style.css are byte-identical, no leftover .research-caveat references, cellulolysis links -falcon.


🔵 The sidecar exclusion spells one convention; the sibling helper spells the other

render_trait_pages.py:245 excludes path.name.endswith(".citations.md"). _edison_capture.py:385 names its sidecar {stem}-citations.md — hyphen, not dot. Today that's harmless, because nothing writes an _edison_capture bundle under a -deep-research- stem. But the two conventions coexist in the tree, and the sweep namespace is the obvious one to reach for if a future caller wires that helper up.

If it ever happens, the failure is silent rather than loud: {slug}-deep-research-<p>-citations.md matches the glob, survives the .citations.md exclusion, and for an unrecognised provider sorts ahead of its own report (- is 0x2D, . is 0x2E, so …-p-citations.md < …-p.md) — the page would render the reference list as the report. A known provider is safe, since RESEARCH_PROVIDERS ranking dominates name order. justfile:515 carries the same shape.

Matching [-.]citations\.md$ in both places would close it, or a line noting that the exclusion is deliberately scoped to the deep-research-client convention. Genuinely optional — it is a latent footgun, not a live one, and I'd rather flag it here than have it found later as a page rendering a bibliography.


No data/traits/** changes, so no history/ record is expected and the ontology / evidence / causal-graph surface is untouched. Nothing else.

Note on verification: pytest and just qc are not executable in this environment, so the 271-pass and exit-0 claims remain unverified by me. Everything above I confirmed by inspecting the tree, the scripts, and the regenerated pages. I also can't submit a formal GitHub review or approve — this comment is the verdict: approve.

· branch fix/render-research-filename ·

)

The tree spells this two ways. The deep-research-client pipeline writes
`<report>.md.citations.md`; _edison_capture bundles write `<stem>-citations.md`.
The renderer excluded only the dot form.

They cannot collide today — research_trait_edison.py builds an `-edison-` stem,
so nothing that helper writes lands in the `-deep-research-` namespace. The
reason to fix it anyway is the failure mode if that ever changes: a hyphen-form
sidecar matches the glob, survives a dot-only exclusion, and for an
UNRECOGNISED provider sorts ahead of its own report, because '-' is 0x2D and
'.' is 0x2E. The page renders the bibliography as the report, silently, and only
for a new provider — precisely when nobody is looking for it. A recognised
provider is safe, since RESEARCH_PROVIDERS ranking dominates name order.

Confirmed rather than reasoned about: with the old exclusion the candidate set
is ['x-deep-research-zeta-citations.md', 'x-deep-research-zeta.md'] and min()
picks the citations file. Both conventions are now pinned by a parametrised
test that fails against the old code.

The justfile's untracked-report guard had the same shape and gets the same fix.

273 tests pass, `just qc` exits 0.

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

culturebot-reviewer Bot commented Aug 5, 2026

Copy link
Copy Markdown

Claude finished @realmarcin's task in 1m 42s —— View job


Review

The only change since the last approval is the sidecar exclusion, and it is correct.

The regex does what the commit message says. [-.]citations\.md$ against the three names that matter: x-deep-research-zeta.md survives, x-deep-research-zeta.md.citations.md and x-deep-research-zeta-citations.md are both dropped. The ERE swap in the justfile (grep -v '\.citations\.md$'grep -Ev '[-.]citations\.md$') is the same predicate — [-.] puts the hyphen first, where it is literal, and \. is a literal dot in ERE as well as BRE. Both sides of the fix stay in step, which was the point of touching justfile:517 at all.

The corpus still matches the premise. 707 tracked files under research/traits, all dot-form: zero names end in -citations.md. So the hyphen branch is latent, as the message claims, and research_report() selects exactly what it selected before — which is why this commit correctly carries no pages/ diff. Nothing in the rendered output moves.

The parametrised test is the right shape. Both conventions are asserted against the same report, and the hyphen case genuinely fails against the pre-commit code — under the old endswith(".citations.md") the candidate list is ['x-deep-research-zeta-citations.md', 'x-deep-research-zeta.md'] and rank() falls to name order for an unknown provider, so min() returns the sidecar. It does not duplicate test_citation_sidecar_is_never_picked, which pins the different case of a sidecar with no report beside it.

The comment at render_trait_pages.py:244-250 is longer than the line it explains, but it records why an unreachable branch is being defended — the failure would be silent, provider-specific, and would render a bibliography as findings. That is the part a future reader would otherwise delete.

Still verified from earlier rounds: 353 pages carry a block, all 353 carry the .graph-warning caveat, src/…/style.css and pages/assets/style.css are byte-identical, cellulolysis links -falcon.

No data/traits/** changes, so no history/ record is expected and the ontology / evidence / causal-graph surface is untouched. Nothing to raise.

Note on verification: command execution is sandboxed here — pytest and just qc would not run, so the 273-pass / exit-0 claims are unverified by me; the regex and ranking analysis above is static. I also cannot submit a formal GitHub review or approve, so this comment is the verdict: approve.
· branch fix/render-research-filename

@realmarcin
realmarcin merged commit 715a947 into main Aug 5, 2026
5 checks passed
@realmarcin
realmarcin deleted the fix/render-research-filename branch August 5, 2026 00:10
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 per-trait research block never renders: the renderer and the research pipeline disagree on the filename

1 participant