@daviddao

Plurality Wiki · Frontend audit · round 1

Test Report

A careful walk-through of the 86-page static site built in wiki/frontend/dist/, testing Markdown rendering, wikilink resolution, math typesetting, and interactive behaviour. Auditor: Claude, 2026-04-17.

Scope: every page reachable from the homepage · 20-step interactive tour · static link integrity scan · content pattern scan (wikilinks, math, dead-links).

Superseded — see the latest report. Round 2: v2. Round 3 (rename + Eval Cards): v3. Round 4 (validity-frame landing page + wide hubs): v4.

Headline findings

SeverityIssueCount
failLaTeX is rendered as raw $$…$$ text, not math5 pages (Gini, Atkinson, Theil, NSW, EF1)
failBroken relative link ../../raw/papers/_parsed/ on ontology page1 link
warnUnresolved wikilinks rendered as dead-link spans48 spans across 7 pages
warnUnprocessed [[_ontology §1]] literal wikilinks in AIR page5 occurrences
warnDuplicate title: frontmatter title & H1 both rendered at large sizeAll 86 pages
warnGraph: node labels overlap hub nodes when simulation settlesgraph page
warnSearch result rendering concatenates family+title+title+excerptsearch page
warnHome "10 metric families" grid shows 11 cards + a "Hub" cardhome
warnEmpty grid cell on home when family count is odd (11)home
warn§8 Institutional design & §11 Post-deployment have blank card bodieshome
warnNo branded 404 page (raw SimpleHTTPServer error shows)404s
passMasthead, typography, and page layout render correctlyall pages
passBacklinks block ("Mentioned in") populated on every pageall pages
passCitation sources resolve to /sources/*.txt when available41 valid sources
passGraph legend enumerates all 12 families (incl. §11 + Hub)graph page
passMasthead drawer (Menu) opens and closesall pages
passClient-side search returns relevant resultssearch page

Screen recording

Full 20-step tour of the frontend, captured with agent-browser while the Python static-file server served dist/ on :8000.

Download WebM (1.0 MB)


Issues

critical · math rendering

LaTeX is not typeset — raw $$...$$ shows as literal text

The 5 pages with math (Gini, Atkinson, Theil, Nash Social Welfare, EF1) ship their formulas as $$ … $$ wrapped in a <p> tag. No KaTeX or MathJax pipeline is installed. Why this happened: the BRIEF.md didn't call out math, so the plan didn't include a math renderer. The synthesis pages were written with proper LaTeX expecting it to render.

Gini page showing raw LaTeX
Gini page: formula appears as $$G = \frac{1}{2n^{2}\mu} \sum_{i} \sum_{j} |y_{i} - y_{j}|$$ instead of rendered math. Range annotation and Italic title survive fine.
Atkinson page
Atkinson: A_{\varepsilon} = 1 - \frac{1}{\mu}\left[…\right]^{1/(1-\varepsilon)} raw.
EF1 page
EF1: \forall i,j ; \exists g \in A_{j} : … raw.

Fix: add remark-math + rehype-katex to astro.config.mjs, pull in KaTeX CSS in BaseLayout.astro. ~15 lines.

critical · link integrity

Broken link ../../raw/papers/_parsed/ on ontology page

The rendered _ontology.md has an anchor pointing to ../../raw/papers/_parsed/ — a directory listing link that made sense in the source markdown but does not exist under dist/. Astro's check-links hook was configured to pass on absolute root URLs but missed relative-to-current-page hrefs.

Fix: either (a) rewrite the reference in _ontology.md to /sources/, or (b) have the wikilinks plugin also intercept markdown [text](../../raw/papers/_parsed/…) links.

critical · wikilink resolver

Unprocessed [[_ontology §1]] wikilinks on AIR page

The post-deployment-cluster page aggregated-individual-reporting.md contains 5 wikilinks of the form [[_ontology §1]] (slug with a literal space + §n). The resolver regex expects [[slug]] or [[slug|label]], so these pass through as literal [[…]] in the rendered HTML.

AIR page showing dead links
AIR page — the body renders fine, but the See-also section further down shows the literal [[_ontology §1]] strings (off-screen here; inspected in HTML source).

Fix: relax the wikilink regex to accept spaces + §\d+, then resolve them to /ontology/#section-slug.

warn · wikilink resolver

48 dead-link spans across 7 post-deployment pages

The §11 post-deployment cluster references concepts/* and sources/* pages that don't exist yet — the cluster was written before the corresponding concept/source pages were created. The renderer honours the plan's dead-link styling (muted, no underline), so this is not a bug in the renderer — it's a content-layer gap. Top labels: sources/dai-2025-reporting-database (6×), concepts/ex-ante-policy (5×), concepts/reporting-database-problem (4×), concepts/sequential-hypothesis-test-for-harm (4×).

AIR page with grey dead-link spans
AIR page: grey (dead) links AIR, individual reports, sequential tests are rendered as <span class="dead-link"> per the plan. Works as designed, but 48 of them across the §11 family looks messy.

Fix: create the 14 missing concept + source pages under wiki/pages/concepts/ and wiki/pages/sources/, or update the §11 pages to inline the definitions.

warn · templates

Every page shows the title twice at display size

The PageLayout renders the frontmatter title as a large <h1> in the sidebar + the markdown body's first H1 (also large). Because the synthesis pages start with # Metric Name that matches the frontmatter title, users see the title rendered twice at identical size, stacked.

Bridging-score page title repeated
Bridging Score page: "Bridging Score (Pol.is)" appears in the top hero block AND again as a body H1 below. Aesthetically redundant.

Fix: strip the first H1 from the markdown body at render time, or make the body H1 render at a smaller size.

warn · graph interaction

Graph labels overlap hub nodes

When the force simulation settles, the two largest hub nodes (_ontology, _mve-stack) draw their <text> labels directly on top of themselves, occluding the node circle. Since node size is proportional to inbound-link count and the hub has 63 edges, it's always the biggest node — and always the one most covered by its own label.

Ontology graph with labels on nodes
Graph hero: "Evaluation metrics — ontology hub" label sits on top of the central black node. Should offset the label or hide it until hover.

Fix: only render labels on hover, or offset label by r + 6px below the node, or show labels only for nodes above a size threshold.

warn · search

Search result rows show family + title + title + excerpt concatenated

Every result row reads like meta Bridging-based ranking Bridging-based ranking Generalisation of the Pol.is bridging score…. The family key (meta, bridging, …) is a raw identifier, not a label, and the title is repeated because it's both in the result title slot and the FlexSearch-matched snippet.

Search results for bridging
Search "bridging" — results are functional (6 relevant hits, top match is right) but formatted as concatenated strings instead of structured rows.

Fix: format search hits as <div><h4>{title}</h4><p class="family">{familyLabel}</p><p class="excerpt">{snippet}</p></div> instead of joining with spaces.

warn · homepage

Home "10 metric families" grid actually shows 11 + a "Hub" card

When §11 Post-deployment evaluation was added and a new hub family was introduced, the homepage family-card grid started iterating over all families in sections.ts. Result: 12 cards, of which one has an empty body ("HUB" with no description) and two (§8, §11) have almost no description. The section title still reads "10 metric families".

Home mid-grid with Hub card
Left: standalone "HUB" card with no description and next to a card for §3 Summarization.
Home bottom showing §11 empty grid cell
Right: §11 Post-deployment family card with no description, paired with an empty grey placeholder.

Fix: (a) exclude the hub family from the home grid, (b) update the section title to "11 metric families", (c) add a one-sentence description for §8 and §11 to the FAMILIES map or pull from _ontology.md.

warn · 404

No branded 404 page

Visiting a non-existent URL returns the raw Python HTTP server error. On a static host (Netlify, GitHub Pages) this would show the host's default error page instead of our site's layout.

Unbranded 404
/nonexistent-page-x/ — raw SimpleHTTPServer text, no masthead or styling.

Fix: add src/pages/404.astro with a minimal "not found, back to home / ontology" layout. Astro emits it as dist/404.html automatically.


What works well

Homepage hero

Plurality Wiki home hero
Centered serif wordmark, thesis quote from _ontology.md with italicised tradition names, and two call-to-action links. Near-perfect execution of the atmos.earth restraint cue.

Featured metrics strip

Featured metrics
Row of 5 metrics ranked by inbound backlinks (13 / 12 / 11 / 10 / 10) — Mechanism Robustness Score, Nash Social Welfare, AIR, Strategyproofness, Tension (fidelity vs strategyproofness). The 10-family grid begins below.

Tension page

Bridging vs JR tension
Tension page: eyebrow "§10 Tensions", large serif H1, wikilinks (Pol.is bridging, JR) underlined and working, sidebar sources link to /sources/small-2023-polis-llms.txt and /sources/fish-2024-generative-social-choice.txt.

Section index

§2 section page
§2 Bridging section page: lists all 12 metrics in family with hover-able slugs in the right column. Accent bar + sidebar "All families" ← back link.

§11 section page (new family)

§11 section page
§11 Post-deployment evaluation renders cleanly with all 5 metrics, even though the family was added after the initial build and required a patch to sections.ts. The patch worked.

Ontology graph (legend)

Graph legend full view
Scrolled view of the graph page shows the complete 12-family legend beneath the SVG. Colour tokens match those used by the family cards and metric-page eyebrows.

Search overlay / page

Search page empty
Empty-state search page. Typing "bridging" loads the client-side FlexSearch index and returns 6 relevant hits within < 250 ms (after lazy index load).

Appendix — complete screenshot catalog

Every screenshot captured during the audit tour, in order.

StepURLShot
1/ top01-home-top.png
2/ featured strip02-home-featured.png
3/ mid grid02-home-mid.png
4/ bottom03-home-bottom.png
5/ footer03b-home-footer.png
6/ontology/ top04-ontology-top.png
7/ontology/ mid05-ontology-mid.png
8/mve-stack/06-mve-stack.png
9/graph/ top07-graph-top.png
10/graph/ settled07b-graph-settled.png
11/graph/ full (legend)07c-graph-full.png
12/graph/ scrolled08-graph-zoom.png
13/bridging-score/09-metric-bridging.png
14/gini/10-metric-gini-LATEX.png
15/atkinson/11-metric-atkinson-LATEX.png
16/nash-social-welfare/12-metric-nsw-LATEX.png
17/ef1/13-metric-ef1-LATEX.png
18/theil/14-metric-theil-LATEX.png
19/tension-bridging-vs-jr/15-tension-page.png
20/sections/bridging/16-section-bridging.png
21/sections/post-deployment/17-section-postdeploy.png
22/aggregated-individual-reporting/ top18-air-page-DEADLINKS.png
23/aggregated-individual-reporting/ mid19-air-deadlinks-mid.png
24/incidence-rate-from-reports/20-incidence-page.png
25masthead Menu open21-menu-open.png
26/search/ empty22-search-empty.png
27/search/ "bridging"23-search-bridging.png
28/gini/ close-up24-gini-close.png
29404 on non-existent URL25-404.png

Reproducing the tests

cd wiki/frontend
npm run build
python3 -m http.server 8000 -d dist &

# Static analysis (both ran from project root):
python3 tests/scripts/check-links.py          # internal-link integrity
python3 tests/scripts/check-content.py        # wikilink/math/deadlink scan

# Interactive tour + screen recording:
bash tests/scripts/tour.sh                    # runs the 20-step tour, records WebM

Auditor: Claude · 2026-04-17 · Report: tests/index.html · Video: tests/artifacts/full-audit.webm.