Found while building the pages/ staleness gate (#230), checking whether a gitignored input could wedge it.
The mismatch
render_trait_pages.py:286 looks for:
research/traits/<category>/<slug>.md
run_trait_graph_audit.py — and the deep-research-trait skill — write:
research/traits/<category>/<slug>-deep-research-falcon.md
The provider suffix is deliberate there; it is what makes the sweep resumable, since resume detection is file-existence based on that exact name.
Consequence
research_md is always empty, so the <pre class="research-md"> block in trait.html and the .research-md rule in style.css are both dead code. This checkout has 23 research files under research/traits/, including cellulolysis, and not one page renders a research section.
Verified by creating the name the renderer expects — research/traits/metabolism/cellulolysis.md — at which point the block appears immediately. So the feature works; it has simply never been pointed at the files that exist.
Why it stayed invisible
research/ is gitignored, so this can only be observed on a machine that has run the research pipeline, and even there the absence looks like "no research for this trait" rather than a lookup bug.
Fix
Match the pattern the pipeline actually writes. <slug>-deep-research-*.md rather than an exact <slug>.md, picking one deterministically if several providers have run — sorting by name and taking the first keeps the render reproducible, which #228 made a requirement.
Interaction with #230, worth deciding together
Once this renders, a curator's build embeds a block that CI's build cannot, because research/ is gitignored. Committing such a page wedges the gate permanently: just gen-pages fixes it locally and CI re-breaks it on every push. #230's gate now detects that collision on both the rendered and committed sides and names it, rather than emitting a bare STALE — but detecting it is not resolving it.
The real options are to stop committing research-bearing pages, to exclude the block from the gate's comparison, or to track the research inputs. That is a decision, not a cleanup, and it should be made before this lookup is fixed rather than after.
Found while building the
pages/staleness gate (#230), checking whether a gitignored input could wedge it.The mismatch
render_trait_pages.py:286looks for:run_trait_graph_audit.py— and thedeep-research-traitskill — write:The provider suffix is deliberate there; it is what makes the sweep resumable, since resume detection is file-existence based on that exact name.
Consequence
research_mdis always empty, so the<pre class="research-md">block intrait.htmland the.research-mdrule instyle.cssare both dead code. This checkout has 23 research files underresearch/traits/, includingcellulolysis, and not one page renders a research section.Verified by creating the name the renderer expects —
research/traits/metabolism/cellulolysis.md— at which point the block appears immediately. So the feature works; it has simply never been pointed at the files that exist.Why it stayed invisible
research/is gitignored, so this can only be observed on a machine that has run the research pipeline, and even there the absence looks like "no research for this trait" rather than a lookup bug.Fix
Match the pattern the pipeline actually writes.
<slug>-deep-research-*.mdrather than an exact<slug>.md, picking one deterministically if several providers have run — sorting by name and taking the first keeps the render reproducible, which #228 made a requirement.Interaction with #230, worth deciding together
Once this renders, a curator's build embeds a block that CI's build cannot, because
research/is gitignored. Committing such a page wedges the gate permanently:just gen-pagesfixes it locally and CI re-breaks it on every push. #230's gate now detects that collision on both the rendered and committed sides and names it, rather than emitting a bare STALE — but detecting it is not resolving it.The real options are to stop committing research-bearing pages, to exclude the block from the gate's comparison, or to track the research inputs. That is a decision, not a cleanup, and it should be made before this lookup is fixed rather than after.