Objective
Restore the Source badge column in the browser-rendered leverage Meta and weighted-Meta catalog rows so tests/test_catalog_leverage_meta.py::test_js_meta_leverage_helpers and tests/test_catalog_leverage_weighted_meta.py::test_js_weighted_meta_leverage_helpers pass without weakening assertions. The live helpers had regressed to 8 <td> and omitted class="badge non-as".
Approach
- Reproduced both helpers via the named pytest tests:
8 == 9onhtml.count('<td')and missingclass="badge non-as"on the weighted helper. - Traced root cause to commit
860b01227(align IA templates, no Source), which removed theSourceheader from static catalog tables and simultaneously stripped the second<td><span class="badge as|non-as">cell fromrenderMetaCatalogRowandrenderWeightedMetaCatalogRowindocs/assets/js/catalog-equalize.js. Parent860b01227^had 9 cells (name [+ diversification], Source badge, rebal badge, CAGR, Sharpe, Sortino, max DD, turnover, start date); HEAD emitted 8. - Restored the minimal contract: re-inserted
'<td><span class="badge '+escapeHtml(source)+'">'+escapeHtml(sourceLabel)+'</span></td>'before the rebal badge in both renderers, matching the test contract that requireshtml.count('<td') == 9andclass="badge non-as"forsource='non-as'on the weighted helper. Nosite.jscopies required the same change andemptyStateColspanalready derives colspan fromthead thcount, so empty-state rows stay consistent at 9. - Verified consistency via grep: only
catalog-equalize.jsdefines these renderers;applyMetaLeverage/applyWeightedMetaLeverageconsume them. Template divergence (meta_catalog.html.j2static 8-col) is out of scope for this JS-helper bead and is noted for follow-up. Scope stays minimal — 12 lines in a single file.
Files changed
docs/assets/js/catalog-equalize.js— restoredSourcebadge<td>inrenderMetaCatalogRow(after Name/title link) and inrenderWeightedMetaCatalogRow(after name+diversification badge) before the rebal badge.research/results/qm-hkqu.md— this durable result note.docs/site-data/results.json,docs/results.html,docs/results/qm-hkqu.html— regenerated viapython3 -m research.reports.results.
Validation
python3 -m pytest -q tests/test_catalog_leverage_meta.py::test_js_meta_leverage_helpers tests/test_catalog_leverage_weighted_meta.py::test_js_weighted_meta_leverage_helpers— 2 passed (named AC).python3 -m pytest -q tests/test_catalog_leverage_meta.py tests/test_catalog_leverage_weighted_meta.py— 18 passed (full modules; no sibling breakage).node -erequiringdocs/assets/js/catalog-equalize.js— both helpers emit 9<td>; weighted row withsource='non-as'containsclass="badge non-as".python3 -m research.artifacts check --mode full --offline— deterministic and current.python3 research/scripts/check_static_reports.py docs— local bundle OK.python3 -m research.reports.results— changelog payload rebuilt (docs/site-data/results.json + detail pages).
Results
Both JS helpers now satisfy the 9-column contract exercised by the two named tests without assertion weakening. Greps confirm no other JS duplicates needed the same fix and call sites (applyMetaLeverage, applyWeightedMetaLeverage, emptyStateColspan) are consistent. Publication artifacts are deterministic via canonical producers.
Risks / Limitations
Static server-rendered meta catalog templates that still emit 8-column rows without Source remain diverged from the JS contract and rely on hideSourceColumn to hide the column at render time. That template path was explicitly out of scope for this JS-helper bead.