Render the research block by looking for the file the pipeline writes (#233) - #253
Conversation
…#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>
|
Claude finished @realmarcin's task in 4m 30s —— View job ReviewThe 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:
Two things. 🟡 The caveat does not read as a warning, and this stylesheet already has one that does
Meanwhile 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; 🔵 The guard's premise is coarser than the divergence it describes
The narrower case survives: a curator runs a new sweep, renders, and commits 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 Note on verification: I could not execute Requesting changes on the caveat styling alone; the 🔵 is optional. · branch |
There was a problem hiding this comment.
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>
|
Claude finished @realmarcin's task in 2m 58s —— View job Review
The blocking item is resolved and the three follow-ons landed cleanly. The caveat now reads as a warning.
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" ( The marker anchoring moved to the second occurrence, with the asymmetry argued inline: overshooting leaves boilerplate in the preview, undershooting silently drops findings. 🔵 The guard swapped under-firing for over-firing
Given that 342 reports were lost to precisely this failure ( No Note on verification: · branch |
There was a problem hiding this comment.
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>
|
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
Still verified from the previous round: 353 pages carry a block, all 353 carry the warning, 🔵 The sidecar exclusion spells one convention; the sibling helper spells the other
If it ever happens, the failure is silent rather than loud: Matching No Note on verification: · branch |
) 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>
|
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. The corpus still matches the premise. 707 tracked files under 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 The comment at Still verified from earlier rounds: 353 pages carry a block, all 353 carry the No Note on verification: command execution is sandboxed here — |
Closes #233. Resolves the tie-break half of #245.
render_trait_pages.py:286looked forresearch/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. Soresearch_mdwas always empty, and both the<pre class="research-md">block intrait.htmland 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-falconand-codex— and name order pickscodex, 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 MB —mutualism.html36 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_LINESis 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-reportsrejected 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/traitsis 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
The
pages/diff is 353 trait pages plusassets/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
codexartifact should exist at all — is still a decision, though this PR removes its ability to surface on a page.🤖 Generated with Claude Code