Skip to content

Reference pages: hand-written prose, measured numbers - #15

Merged
HarryCordewener merged 1 commit into
feat/faceted-searchfrom
feat/reference-pages
Jul 31, 2026
Merged

Reference pages: hand-written prose, measured numbers#15
HarryCordewener merged 1 commit into
feat/faceted-searchfrom
feat/reference-pages

Conversation

@HarryCordewener

@HarryCordewener HarryCordewener commented Jul 31, 2026

Copy link
Copy Markdown
Member

Stacks on #11 (chore/park-the-importer), which is main plus #9 and #11. Review the top commit only; merge after #11.

Spec §9's last block — reference pages for clients, codebases and protocols, plus orientation content. §14 counts it in v1. Nothing existed.

The split that makes it worth having

The prose is ours; every number beside it is measured. CodebaseFigures.ReadAsync asks IGameQueries for exactly the filter the page's "see the games" link carries, so the headline count and the listing a reader lands on are one query and cannot drift. A codebase page whose "47 games" is a hand-typed number is indistinguishable on the page from the honest version, so it is made impossible rather than discouraged — no count lives in a content file, and ACodebaseCountMovesWhenTheCatalogueMoves asserts the figure tracks the query rather than merely that a number renders.

What is in it

  • /reference — index, plus /reference/codebases/{slug}, /clients/{slug}, /protocols/{slug} and /reference/{slug} for orientation. One nav line.
  • 16 codebase pages, grounded in docs/codebase-survey-2026-07-30.md, each cross-linked to a filtered game listing.
  • 10 protocol pages with an implementation matrix derived from capability.*.measured and never from the MSSP-declared side.
  • 9 client pages with a hand-written capability matrix whose first row is screen-reader accessibility.
  • 3 orientation pages — MUSH vs MUD vs MUCK vs MOO; "you want collaborative RP"; how to connect.

Markdown, and why

Content is content/reference/*.md, embedded into the assembly, rendered per request with Markdig. Razor would have saved the dependency and cost the thing the section exists for: §9's argument is that this obtains wiki value without wiki governance, governance here means review, and review of prose only works if the diff reads as prose. A codebase description inside a component arrives in a PR as escaped literals interleaved with layout.

Structured claims live in a key: value front-matter block read by ~100 lines of our own parser — eight keys, no nesting, no YAML dependency. An unknown key throws at load, because a mistyped capabilty: silently dropping a matrix row is exactly the shape of wrong that looks right here.

No external hosts is enforced by the pipeline, not by editorial care. Raw HTML is disabled and an image is rewritten into a link to the same URL, so no content file can make a rendered page fetch from anywhere. ProseCarriesNoRemoteAsset asserts it on the rendered output of every shipped page.

Unknown never renders as no

A client has no handshake of ours to observe, so every cell is a reading of somebody's documentation and the citation is the load-bearing part of the record. CapabilityClaim.Read demotes any state arriving without a source to Unknown — in both directions, because "this client does not do MXP" is as much a claim as the opposite. An unknown that reads as a no is the heatmap defect wearing different clothes.

44 of the 90 client cells say unknown. That is the honest number, and the table at the bottom lists what could not be established, per client.

Screen-reader accessibility is present on every client page whether or not anybody established it: an omitted row and an unknown row are the same fact with only one of them legible. Both arms exist in the shipped content and a test requires both — a column that is all-unknown teaches a reader to ignore it, and one that is all-yes is not a column anybody checked.

Protocol matrices carry no complement

"12 of 40 PennMUSH games offered CHARSET" leaves 28 that did not offer it to us — a set mixing servers without it and servers whose handshake we have not read. ProtocolByCodebase carries Identified and Offering and no third number, so there is nothing for a renderer to reach for, and a test asserts no member of that type is named for an absence.

Plain mode

Everything renders under ?plain=1 from the same records. Markdig's own ToPlainText was not usable — it collapses heading, paragraph, bullet and code block into one unwrapped line each, which is the page with its structure removed. The plain renderer walks the AST instead: headings, hanging list markers, literal blocks left literal, everything wrapped at eighty columns except a citation URL, which cannot be wrapped and still be a URL.

Catalogue change

GameFilter grows a Codebase facet, matched by CodebaseFamily as a bounded prefix — every patchlevel of PennMUSH gathers, ROMulus does not join ROM, LambdaMOO does not join MOO. It is applied after FieldPrecedence rather than in the WHERE clause, for the reason NpgsqlGameQueries already refuses to write the ladder in SQL: a query picking its own row would filter on one source and display another. /games and /api/games learn the same spelling, because the facet panel's field names are the public query language.

Capability claims I could not source

Listed per the brief. None of these is a no; several are probably yes and I could not show it.

Client Could not establish
Mudlet MCCP — implemented in source, absent from the manual's protocols page
MUSHclient MSDP, GMCP (only an example plugin, not shipped support), TLS (unreleased master only), UTF-8/CHARSET (unreleased 5.07 notes only), screen reader (a bundled SAPI TTS plugin is not screen-reader support; no accessibility docs)
TinTin++ ATCP; MCCP v1/v2 distinction; native MXP and MSP (community scripts only)
Potato GMCP, MSDP, MCCP, MXP, MSP, ATCP, screen reader — a sweep of the site, 103 wiki helpfiles and the source tree found no documented statement about any of them
BeipMU MSDP, MCCP, MXP, MSP, ATCP; and which screen readers it works with
Atlantis GMCP, MSDP, ATCP, MSP, MXP, MCCP version, licence/price, any release date, screen reader
VIP Mud GMCP, MSDP, MCCP, MXP, ATCP, TLS, UTF-8, the scripting language's name, any release date, whether it is still developed after the 2025 acquisition
TinyFugue GMCP, MSDP, MXP, MSP, ATCP, UTF-8, screen reader
Blightmud MXP, MSP, ATCP, MCCP v1

Three near-misses that would each have produced a false yes and are called out in the prose: BeipMU's MCMP is not MSP; Atlantis's Atlantis::Speak() is a scripting call in a scripting system the project says no longer works, not screen-reader support; TinyFugue's expnonvis.html "non-visual mode" is about input-line handling and mentions no assistive technology.

The one sourced no in the whole section is Atlantis's scripting, which the project's own home page says stopped working.

Deliberately left out

  • Rankings and ecosystem-share pages. Adjacent and separately scoped.
  • Client and codebase release tracking. Spec §14 puts it out of v1 explicitly.
  • A page per surveyed codebase. 16 of 38; the remainder are one-game families where a page would be a stub.
  • Aliases for a codebase family. One page declares one prefix, so a family with several spellings needs the canonical one chosen. Nothing in the survey needs it yet.
  • A 404 status for a missing reference page. It renders the not-found body with a 200, matching Game.razor; changing that is a site-wide decision.

Verification

dotnet build MUIndex.slnx -c Release — clean, no warnings. All five suites green: Catalog 139, Crawl 130, Crawler 77, Discovery 182, Web 144. Every route checked against a running site in fixture mode, graphical and plain.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NrGKmKcRCGktyhRTFbQDMk

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 92226e1d-0ac7-4305-a2e8-c6b4119b3928

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@HarryCordewener
HarryCordewener changed the base branch from main to chore/park-the-importer July 31, 2026 15:18
Spec §9's last block, and §14 counts it in v1. Clients, codebases, protocols and
orientation content, hand-written and versioned in git — the sanctioned
alternative to a wiki, which is on the Never list.

The split that makes it worth having: the prose is ours and the figures are
measured. "Games running this codebase: 47" comes from IGameQueries on the
request that renders it, over the same filter the page's own listing link
carries, so the headline and the listing behind it are one query and cannot
drift. A codebase page whose count is a hand-typed number is the failure mode,
and it is indistinguishable on the page from the honest version — so it is made
impossible rather than discouraged, and a test asserts the count *moves when the
catalogue moves* rather than merely that a number appears.

Content is Markdown in content/reference/, embedded into the assembly and
rendered per request. Razor would have saved a dependency and cost the thing
the section exists for: governance here means review, review of prose only
works if the diff reads as prose, and a codebase description inside a component
arrives in a PR as escaped literals interleaved with layout. Structured claims
live in a tiny key: value front-matter block read by our own parser — eight
keys, no nesting, no YAML dependency, and an unknown key is an error because a
mistyped `capabilty:` silently dropping a matrix row is the shape of wrong that
looks right here.

The Markdig pipeline is where "no external hosts" is enforced. Raw HTML is
disabled and an image is rewritten into a link to the same URL, so no content
file can make the rendered page fetch from anywhere — a property of the parser
rather than of editorial care.

Protocol pages carry only measured handshakes, and carry no complement.
"12 of 40 offered CHARSET" leaves 28 games that did not offer it *to us*, a set
mixing servers without it and servers whose handshake we have not read;
ProtocolByCodebase has no third number for a renderer to reach for.

Client matrices are hand-written, because a client has no handshake of ours to
observe — so the citation is the load-bearing part of the record, and
CapabilityClaim.Read demotes any state arriving without a source to unknown, in
both directions. An unknown that reads as a no is the heatmap defect wearing
different clothes. Screen-reader accessibility is the first row of every client
page whether or not anybody established it: spec §9 names it, no incumbent
publishes it, and an omitted row and an unknown row are the same fact with only
one of them legible. Forty-four of the ninety cells across nine clients say
unknown, and that is the honest number.

Everything survives ?plain=1, rendered off the same records. Markdig's own
ToPlainText was not usable: it collapses heading, paragraph, bullet and code
block into one unwrapped line each, which is the page with its structure
removed — so the plain renderer walks the AST instead.

GameFilter grows a Codebase facet, matched as a bounded prefix so every
patchlevel of PennMUSH gathers and ROMulus does not join ROM. It is applied
after FieldPrecedence rather than in the WHERE clause, for the reason that class
already refuses to write the ladder in SQL. /games and /api/games learn the same
spelling, because the panel's field names are the public query language.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NrGKmKcRCGktyhRTFbQDMk
@HarryCordewener
HarryCordewener changed the base branch from chore/park-the-importer to feat/faceted-search July 31, 2026 15:30
@HarryCordewener
HarryCordewener merged commit 8e2bc5d into main Jul 31, 2026
1 check passed
@HarryCordewener
HarryCordewener deleted the feat/reference-pages branch July 31, 2026 15:53
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.

1 participant