Skip to content

The README a stranger reads, and the wiki that holds the rest [#333] - #347

Merged
iderex merged 1 commit into
masterfrom
docs/333-the-readme-a-stranger-reads-signed-off
Sep 6, 2026
Merged

iderex merged 1 commit into
masterfrom
docs/333-the-readme-a-stranger-reads-signed-off

Conversation

@iderex

@iderex iderex commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Closes #333. Stage 4 of 9 on #329.

This replaces #346, whose single commit carried no Signed-off-by trailer and
reddened the DCO gate. The content is identical; the branch is a new name rather
than a rewrite of the old one, and #346 is closed with that reason in its body.

Scope: README.md, and this repository's wiki. img/ is unchanged: the logo it
already holds is what the new header shows, and nothing else was needed.

What was wrong

The README was written for somebody working in the tree. It pasted grep output,
argued the version scheme, and quoted a workflow run and its log. A stranger who
wanted to know what the plugin is, whether it is for them, and how to install it
read 180 lines to find one address.

Two of its statements had gone false, because a paste goes stale the moment the
tree moves. It said the page a user opens about their own numbers was not built
while the routes behind it exist, and its pasted action list named eight of the
ten actions on the tree:

$ grep -c 'ActionResult<' Jellyfin.Plugin.Stats/Api/*.cs | awk -F: '{s+=$2} END {print s}'
10

The wiki held one page, the welcome text.

What this changes

README.md, 168 lines in place of 180, eight sections that link out rather
than explain: what it is, what it is not, installing, configuration,
documentation, privacy and security, contributing, licence. Above them a note
block naming Flowfin, the status rung and where installing is described, a
centred title with the logo out of img/, and six badges: licence, the latest
release of each version stream, build status, documentation, OpenSSF Scorecard.

No command output is pasted anywhere in it, so nothing is left in this file that
can go stale against the tree without a reader noticing.

Who sees what is the rule of #329 in the same words: a signed-in account sees
its own figures and nobody else's, no route hands one account another account's
rows, an administrator is refused there like anybody else, the server-wide
reports name nobody, and the one place an account is named is the server's year
in review where that account recorded its own agreement.

Nothing in it promises a page the installed version shows. It states that no
statistics page is drawn in the dashboard today, says why in two sentences, and
names the views as arriving with 0.2.0.0 under #335, #336 and #337.

The wiki, ten pages and a sidebar, pushed separately because a wiki is its
own repository:

$ git -C <wiki clone> log --oneline -1
c2124f9 The wiki a reader is sent to from the README [#333]
$ git -C <wiki clone> ls-tree --name-only HEAD
Configuration.md
Home.md
Installation.md
Pages.md
Privacy-consent-and-deletion.md
Release-process.md
Support-matrix-and-releases.md
Transcode-reasons.md
Troubleshooting.md
What-is-stored-and-who-can-read-it.md
_Sidebar.md

Home carries what the plugin is, the status rung and the page list. Installation
carries the address, the catalogue, the restart, the two lines and their version
streams, upgrading, uninstalling and what removal deletes. Pages describes every
view, the states each one tells apart and where it is found. Configuration puts
the eight settings in a reader's words, both retention windows, and which of the
two deletions is terminal. What is stored and who can read it carries the
tables, the readers and the absences. Privacy, consent and deletion quotes the
wording in full and separates what agreeing changes from what it does not.
Transcode reasons says why the reason counts exceed the plays. Support matrix
and releases carries the two lines, the floors, the streams, the release assets
and gh attestation verify. Troubleshooting carries the three settings-page
sentences, the refused save, and every line this plugin writes to the server log
with its level. Release process is for whoever cuts a release.

Every page that summarises a tracked document links to it and says the document
is the one to trust on a number, because the suite reads those and reads nothing
on the wiki. The tracked documents under docs/ are untouched.

Pages is marked as coming at the top and at each view, because the installed
version declares its settings page and nothing else.

Done when, against the tree

The README fits in one screen of headings, carries no pasted command output,
and states the catalogue address and the two server lines.

$ grep -c '^## ' README.md
8
$ grep -n '^    \|^```' README.md | head
82:```text
84:```
158:```text
162:```
$ grep -n 'flowfin.dev/manifest.json' README.md
83:https://flowfin.dev/manifest.json

The two fenced blocks are the catalogue address and the build commands. Neither
is output.

Every link in it resolves, checked with a link walker whose output is pasted.
The walker takes every markdown link and every href and src in the file,
deduplicates them, and reports an HTTP status for a remote one, file for a path
that exists in the tree, and anchor for a heading in the file itself:

grep -oE '\]\([^)]+\)|(href|src)="[^"]+"' README.md |
  sed -E 's/^\]\(//; s/\)$//; s/^(href|src)="//; s/"$//' |
  sed 's/&amp;/\&/g' |
  sort -u |
  while IFS= read -r u; do
    case "$u" in
      http*) printf '%s  %s\n' "$(curl -s -o /dev/null -w '%{http_code}' -L "$u")" "$u" ;;
      \#*)   a=$(printf '%s' "$u" | tr -d '#')
             if grep -qiE "^#+ .*$(printf '%s' "$a" | tr '-' ' ')" README.md; then
               printf 'anchor  %s\n' "$u"
             else printf 'MISSING %s\n' "$u"; fi ;;
      *)     if [ -e "$u" ]; then printf 'file    %s\n' "$u"
             else printf 'MISSING %s\n' "$u"; fi ;;
    esac
  done

Run at this branch's head, after the wiki was pushed:

anchor  #installing
file    CHANGELOG.md
file    docs/configuration.md
file    docs/plugin-data.md
file    docs/support-matrix.md
file    docs/transcode-reasons.md
file    docs/what-is-stored.md
file    docs/what-the-log-contains.md
200  https://api.securityscorecards.dev/projects/github.com/Flowfin/jellyfin-plugin-stats/badge
200  https://github.com/Flowfin
200  https://github.com/Flowfin/jellyfin-plugin-stats/actions/workflows/test.yaml
200  https://github.com/Flowfin/jellyfin-plugin-stats/actions/workflows/test.yaml/badge.svg
200  https://github.com/Flowfin/jellyfin-plugin-stats/blob/master/LICENSE
200  https://github.com/Flowfin/jellyfin-plugin-stats/issues/335
200  https://github.com/Flowfin/jellyfin-plugin-stats/issues/336
200  https://github.com/Flowfin/jellyfin-plugin-stats/issues/337
200  https://github.com/Flowfin/jellyfin-plugin-stats/releases
200  https://github.com/Flowfin/jellyfin-plugin-stats/security/advisories/new
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Configuration
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Installation
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Pages
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Privacy-consent-and-deletion
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Release-process
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Support-matrix-and-releases
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Transcode-reasons
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/Troubleshooting
200  https://github.com/Flowfin/jellyfin-plugin-stats/wiki/What-is-stored-and-who-can-read-it
200  https://img.shields.io/badge/docs-wiki-blue
200  https://img.shields.io/github/license/Flowfin/jellyfin-plugin-stats.svg
200  https://img.shields.io/github/v/release/Flowfin/jellyfin-plugin-stats?filter=0.*&display_name=tag&label=Jellyfin%2010.11
200  https://img.shields.io/github/v/release/Flowfin/jellyfin-plugin-stats?filter=1.*&display_name=tag&label=Jellyfin%2012
200  https://raw.githubusercontent.com/Flowfin/jellyfin-plugin-stats/master/img/logo.png
200  https://securityscorecards.dev/viewer/?uri=github.com/Flowfin/jellyfin-plugin-stats
file    LICENSE
file    NOTICE.md
file    SECURITY.md

37 links, no MISSING line. What that walker cannot see is a link inside prose
written without markdown syntax, and there is none in the file.

The two release badges answer rather than erroring, which is the check worth
making on a filtered badge:

$ curl -s 'https://img.shields.io/github/v/release/Flowfin/jellyfin-plugin-stats?filter=0.*&display_name=tag' | grep -o '<title>[^<]*</title>'
<title>release: v0.1.0.0-stable</title>
$ curl -s 'https://img.shields.io/github/v/release/Flowfin/jellyfin-plugin-stats?filter=1.*&display_name=tag' | grep -o '<title>[^<]*</title>'
<title>release: no matching releases found</title>

no matching releases found is the true answer for the 12.0 stream and is what
the badge should say until that line publishes.

Every wiki page above exists with the content listed, the sidebar links them,
and each page that summarises a tracked document links to it.
Every page
answered over HTTP after the push:

200  Home
200  Installation
200  Pages
200  Configuration
200  What-is-stored-and-who-can-read-it
200  Privacy-consent-and-deletion
200  Transcode-reasons
200  Support-matrix-and-releases
200  Troubleshooting
200  Release-process

Nothing in either promises a page the installed version does not show. The
declared set is one page, and that is what the README and the Pages wiki page
both say:

$ grep -c 'new PluginPageInfo' Jellyfin.Plugin.Stats/Plugin.cs
1

The README says the same thing about who sees what as the rule on #329.
That paragraph is quoted above and is in ## What it is.

The means

Markdown in the repository and on the wiki, which is what a README and a wiki
page are made of here and what every reader of them already has. Nothing is
added: no generator, no runtime, no dependency, and the link walker is a shell
pipeline in this body rather than a tool in the tree, so the change adds no file
to maintain. What it cannot carry is a refusable property, which is why the
reading below is stated as a reading.

What this does not do

Nothing checks any of it. No test reads README.md and no route reads a wiki
page, so the link walk above is a reading taken at this head and not a gate: a
link that rots tomorrow turns nothing red. The wiki is outside every check this
repository runs, by construction, which is why each page there says the tracked
document is the one to trust on a number.

The status rung in the note block is a judgement, not a measurement. Nothing in
the tree declares a rung, and In-Development is my reading of a plugin with one
release, a store that will not open on the floor server of its line, and no
statistics page shown anywhere.

img/ is untouched. The banner-shaped header image the sibling boards carry
does not exist here, so the header shows the logo the repository already has.

Checks

Run on this machine at this head. Neither the suite nor the invariants read
README.md, so both are evidence that nothing else moved rather than evidence
about the change:

$ git diff --name-only origin/master...HEAD
README.md
$ sh tools/invariants/lint.sh | tail -1
21 rule(s) checked over the tree, no match.
$ git grep -c -P '\x{2014}' HEAD -- . ; echo "exit=$?"
exit=1

The last one is #340's condition, still met: this file writes no em dash, and no
character above ASCII at all.

This change has had no second reader. The repository's checks on this pull
request are what stands in front of the merge, and a person has read nothing.

The README was written for somebody working in the tree. It pasted grep output,
argued the version scheme, quoted a workflow run and its log, and a stranger who
wanted to know what the plugin is, whether it is for them and how to install it
read 180 lines to find one address. Two of its statements had also gone false,
because a paste goes stale the moment the tree moves: it said the page a user
opens about their own numbers was not built while the routes behind it exist,
and its pasted action list named eight of the ten actions on the tree.

What replaces it is eight sections that link out rather than explain: what it
is, what it is not, installing, configuration, documentation, privacy and
security, contributing, licence. No command output is pasted, so there is
nothing left in this file that can go stale against the tree without a reader
noticing. The catalogue address and the two server lines are stated where a
person installing it looks, and the sentence about the leading number saying
which line a release is for stays, because that is the misreading the numbering
invites.

Who sees what is the rule of #329, in the same words: a signed-in account sees
its own figures and nobody else's, the server-wide reports name nobody, and the
one place an account is named is the server's year in review where that account
recorded its own agreement. Nothing here promises a page the installed version
shows, and the views are named as coming with 0.2.0.0 rather than described as
present.

The rest moved to the wiki, ten pages with a sidebar, pushed separately because
a wiki is its own repository. The tracked documents under docs/ stay where they
are, because the suite reads them, and every wiki page that summarises one links
to it and says it is the one to trust on a number.

The em dash is absent, as #340 asked of the tree, and so is every other
non-ASCII character: the tracked markdown on master carried two bytes above
ASCII before this change and carries the same two after it.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex
iderex merged commit a98405a into master Sep 6, 2026
25 checks passed
@iderex
iderex deleted the docs/333-the-readme-a-stranger-reads-signed-off branch September 6, 2026 15:04
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.

The README a stranger reads, and the wiki that holds the rest

1 participant