Skip to content

dexd: the player, extracted and documented for outsiders - #5

Open
eins78 wants to merge 24 commits into
mainfrom
feature/dexd
Open

dexd: the player, extracted and documented for outsiders#5
eins78 wants to merge 24 commits into
mainfrom
feature/dexd

Conversation

@eins78

@eins78 eins78 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What this is

dexd plays one HEVC video artwork in an endless loop on a Raspberry Pi, with no visible break at the loop point, on a machine that is switched off at the mains. It feeds libmpv one stream that never ends, so playback never reaches the end of the file and never seeks — the mechanism, and the measurements behind it, are in The endless stream.

It arrives here from the 4K looping experiment as a package, with documentation written for people who were not part of that work.

What is in it

The playerpackages/dexd: the crate, the Debian packaging, the systemd unit, four commands (dexd, dex-sidecar, dex-exhibit-apply, dex-wait-hdmi) and their man pages. The video, its sidecar and the exhibit config live together in /opt/dex; the package installs no config. Source MIT-0; the shipped binary links libmpv and is a GPL-3+ combined work. The empty packages/dexd submodule, pointing at a repository that no longer exists, is replaced by the crate.

The documentation — 19 pages in two tiers. docs/guides for a venue technician: what dexd is, build a dex card, prepare your video, configure the exhibit, run, check, troubleshoot, reference. docs/design for a developer new to the project: architecture, the endless stream, startup checks, failure handling, the service unit, the sidecar, the exhibit config, packaging, CI, building and testing, Raspberry Pi media capability, roadmap, and the measurement record the other pages cite.

The vocabularydocs/glossary.md: 147 terms, 34 for the user tier and 113 for the developer tier, each reviewed and approved individually. The project's own shorthand is retired: soak → long-running test; seam and the wrap → the loop point, with the defect described plainly; plan codes, references to private documents, device names and card identifiers do not appear. AGENTS.md carries the writing rules, the tone, what a comment is for, and the table of retired words.

The checksscripts/docs-lint.mjs (Node, no dependencies, 89 tests) enforces the mechanical rules against the glossary, the table of retired words and an allowlist where every exception carries a reason. It runs in CI over the documentation, the crate, the man pages, the READMEs and the workflow file itself, so a new comment and a new CI step name are checked like a new page. CODEOWNERS routes the glossary and the rules to the owner.

What a deployed player and a final review changed

An exhibition player and a seven-agent review of the finished text found things the writing could not have found on its own.

From the deployment. dexd and dex-loop ship four of the same files, so an install onto a card running the older package stopped part-way through; Conflicts and Replaces now declare it, and CI reads both fields back out of the built package. A monitor that offers one refresh rate, 59.95 Hz, restarts the player when the mode is spelled out as 2560x1440@60 — the guide had been recommending that exact value, and now says to write auto and why. The auto-mode warning promised the wrong failure: it named a picture at the wrong size, where a video larger than every mode the display offers never appears at all and the player restarts.

From the review. Nine documents, two man pages and a glossary entry described /opt/dex as a FAT partition any computer opens, with the three files edited by putting the card in a laptop. The package makes it an ordinary directory on the root filesystem and the card recipe never creates a partition, so a technician planning that route finds no such volume. dexOS does ship such a partition, at /dexdata, on an image that plays with pi_video_looper — so what a dexd card lacks is that arrangement, not the idea, and the glossary and roadmap now say which. The card recipe told the reader to download the package from the releases page, which carries a 2024 pre-release and no dexd package. Every shipped man page pointed at dex-sidecar(1), which the package deliberately does not install. The rules file put the exhibit config in /etc/dex, which dexd does not read. Both guides said an off counter in the heartbeat means the player never asked for it; dexd asks on every start, and off is where mpv turned the request down — a fault the guides taught an operator to read as a setting. The troubleshooting entry for a sideways picture prescribed the flag that produces one.

A CI step had carried a plan code and a retired word in its name, on every run's page, since the workflow landed. The writing check never saw it because the workflow file was not among the paths CI passed. It is now.

A last read before it was public

A separate final pass read the text as it now stands, which no earlier pass had: every review before it judged a version the corrections then replaced, and applying those corrections rewrote roughly five hundred lines that nobody had read. Five findings would have stopped a reader, and all five were written while fixing the previous round.

A repair that cannot be typed — "give the connector a forced mode with the trailing D alone", where the grammar takes none or WxH@R[D] and nothing else. A migration that fails in exactly the case its own guard exists for. The only documented route to the package needs a GitHub account and expires ninety days after the build, which the page did not say. A design page still claiming a 4K video plays scaled on a 1080p monitor, which the measurement record now says it cannot. And a man page stating the frame rate cannot be read from the video, in a project whose own tool reads it.

Below those: two front doors reporting as results what the measurement record calls the player reporting on itself; a roadmap claiming players are not networked, on a card the guides give SSH; a licence paragraph that appeared to cover submodules under other projects' licences; a CI page claiming the writing check reads the glossary, which every walk skips because it is that check's own input; one observed monitor generalised into "many panels"; and ten cells in the rules table that had been shipping cut off mid-word.

The same pass found three more places calling /opt/dex a partition — the packaging manifest, a doc-comment and the systemd unit — that the earlier sweep of nine documents had missed.

The vocabulary the review left open was decided in full: hung out, the stamp file gloss dropped, artwork reserved for the installation, sink kept with an entry, the sidecar page renamed to what the rules already called it, and layer stopped meaning two things. Time-based media conservation supplied three terms the project had been improvising — artist's supplied master, archival master and exhibition format, the last being exactly what a dex card plays — which settled a word that had been defined twice, differently, on two pages.

Setting a player up is now framed as installing dexOS, one choice in Raspberry Pi Imager: install-dexos.md, with a note that the trixie image carrying dexd is still being built and the manual steps reach the same card meanwhile. docs/README.md maps both tiers, which the design pages had no way into or out of.

AGENTS.md gains a seventeenth rule from those two corrections: the project is unfinished, so a page may name what does not work yet — marked (planned) or as a **Note:** — and an intended arrangement is never written in the present tense. Both defects above were that mistake.

Verification

  • CI green on the branch — changes, build, lint, deny, lifecycle, docs-lint, required. The package builds in a debian:trixie container on an arm64 runner with Debian's own compiler, so the dependencies it derives are the ones the devices have.
  • 258 tests on arm64 in that container: 175 library, 39 command-line, the forced-recovery test against a real mpv run on its own, and 43 across the dex-sidecar, sidecar-writer and FFI-constant targets. dexd links libmpv, so its targets build only where libmpv is present — that is CI, not a macOS workstation.
  • cargo clippy --all-targets -- -D warnings, cargo deny check, reuse lint, shellcheck, checkbashisms, systemd-analyze verify, lintian — clean.
  • Install, remove, purge and autoremove on a real container, asserting no leftovers. Conflicts: dex-loop and Replaces: dex-loop read back out of the built .deb.
  • docs-lint: 0 errors over 53 public files, 16 warnings. 280 relative links resolve, targets and #anchors both — a new rule, added after the review found a link into a section that had been renamed. Four man pages are mandoc -T lint clean.
  • A cold reader with access to only the published pages answered ten operator and developer tasks; a judge scored the answers against the code and the content inventory. The two it could not answer were where to get the package and where the assets live, both fixed.
  • A final pass over the finished text checked every claim it was about to call a blocker against the file and the source it named, and settled its readers' disagreements by reading. Verdict: ship with fixes, and the fixes are in.

Not yet done

  • Playback on hardware with this build. Still the one gap. A device attempt was made in August and is not evidence either way: dexd was given a 3840×2160 video on a 2560×1440 panel, the pairing that cannot work on any build using this player's zero-copy path — dex-loop fails the same way, and did, until it was given the matching video. A fair test needs a video whose size the panel offers.
  • A guide for running dexd on a system you chose yourself — Raspberry Pi OS, DietPi, another Debian — split out from the steps now sitting under Install dexOS. Those steps are that guide in waiting; they are filed under the dexOS page while the image is being built.

Notes for review

The branch before squashing is feature/dexd-unsquashed, if the intermediate steps are of interest. Changes to the vocabulary need a glossary entry and the owner's approval — the lint will reject a term that is in neither the glossary nor the allowlist.

That check reads more than it did. A workflow's own name:, every step's - name: and the text of an ::error:: / ::warning:: / ::notice:: command are prose, because a step name is on every run's page and an annotation reaches whoever reads a failed build — which is where the plan code had been sitting. Turning it on found a retired word in a shipped error message the same minute. In the other direction, a docs/…md#section reference is treated as the path it is, so no rule reads the words in a file name or a heading slug while the link check still resolves them.

eins78 added 24 commits August 19, 2026 03:59
… honest

dexd plays one HEVC video artwork in an endless loop on a Raspberry Pi,
with no visible break at the loop point, on a machine that is switched off
at the mains. It feeds libmpv one stream that never ends, so playback never
reaches the end of the file and never seeks.

The player. The video, its sidecar and the exhibit config live together in
/opt/dex on the card's data partition; the package installs no config. The
sidecar binds the frame rate and a checksum to the video, and dexd refuses
to start rather than guess either. Before opening anything it checks the
display mode, the boot options and the start of the video, and every
refusal names the fix. While playing it checks that playback advances,
recovers in place, writes a heartbeat to the system log, and lets the
service manager restart it if it stops responding. It ships as a Debian
package for arm64 with four commands — dexd(1), dex-sidecar(1),
dex-exhibit-apply(1), dex-wait-hdmi(1) — and their man pages. Source under
MIT-0; the shipped binary links libmpv and is a GPL-3+ combined work. The
empty packages/dexd submodule, which pointed at a repository that no longer
exists, is replaced by the crate itself.

The documentation. docs/guides is for a venue technician who can use a
terminal: what dexd is, building a card, preparing a video, configuring the
exhibit, running and troubleshooting, and a reference of every key, option,
exit code and message. docs/design is for a developer who has never seen
the project: the architecture, the endless stream, the startup checks,
failure handling, the service unit, the sidecar, the exhibit config,
packaging, continuous integration, building and testing, what Raspberry Pi
hardware can do, the roadmap, and the measurement record the other pages
cite. docs/glossary.md holds the terms the documentation may use without
explaining them, each one reviewed and approved.

The rules and the checks. AGENTS.md says how anything an outsider reads is
written — the two audiences, the tone, what a comment is for, the names
that were decided and the words that were retired. scripts/docs-lint.mjs
checks what a machine can check, against the glossary, a table of retired
words and an allowlist where every exception carries a reason; it has 83
tests of its own and runs in CI over the documentation, the crate, the man
pages and the READMEs. CODEOWNERS routes the glossary and the rules to the
project owner. One CI workflow with no path filters builds the package in a
debian:trixie container on an arm64 runner, runs the test suite, cargo-deny,
the shell and unit checks, REUSE, the writing check and an install, remove
and purge cycle, and a single required check reads their results and
decides.
Both packages ship the dex-exhibit-apply and dex-wait-hdmi commands and
their man pages, four files in common. Undeclared, dpkg stops on the first
of them part-way through the install, and the card is left with neither
player configured until someone purges by hand.

Conflicts states the pair is exclusive; Replaces lets apt do the rename in
one step on a card already running dex-loop, which is the upgrade every
existing installation takes.

The allowlist gains the one place the retired name may still be written:
a dpkg field holds a package name, not prose.
The warning told the reader to expect one outcome: the artwork playing at
the wrong resolution with every metric nominal. There is a second, and it
is the one a mismatched exhibit reaches first — a video larger than every
mode the connector offers never reaches the plane at all, the clock does
not advance, and recovery escalates to a restart. An operator reading the
old text would look for a picture that is merely wrong and find a player
that keeps starting.

The repair differs too, so the message now names both. Forcing the mode
helps a display that can build the geometry once forced; it does nothing
for a display that cannot build it at all, where the video is the thing to
change.

Still a warning and not a refusal. The note above it now says why in terms
that hold: "auto" is also the only working value for a panel whose one
refresh is fractional, and refusing here would reject that too.
A player running in an exhibition turned up two things the documentation
did not have, and one it had backwards.

The guide told a technician to set display_mode to 2560x1440@60 or auto
for a 1440p monitor, as though the two were equivalent. On a monitor that
offers its 2560×1440 at 59.95 Hz and nothing else — a common panel, and
the one this was found on — the integer value matches no mode and the
player restarts, with no forced mode involved. A connector whose only
timing is fractional has no working integer display_mode, so auto is not
one option of two but the only one. The guide now says so, the design doc
carries the grammar reason, and the measurement record carries the panel.

The second: a 4K video does not appear at all on that monitor. The
measurement record already held a 4K-file-into-a-1440p-monitor reading
from the detiling path, which does resize; the plane path this design
uses does not, and the two readings look contradictory side by side. The
record now says which path each belongs to.

The troubleshooting table gains the restart-loop case with no mode error,
which is what an operator actually sees, and the message reference gives
both outcomes of the auto warning rather than the milder one.

The roadmap's open question — whether auto should refuse — now carries the
evidence, which argues both ways and so does not close it.
The guides teach artwork.265; the refusal messages and doc-comments still
said loop.265, which is also the file name the superseded package used. A
technician who copied the line dexd printed got a different name from the
one the guide had just given, and neither text said they were the same
thing.

The measurement record keeps loop.265 in the shell pipeline it records:
that is a command someone ran against a file of that name, not an example
to follow.
Nineteen pages that cite each other by name, and nothing checked that the
names still pointed anywhere. One did not: a guide linked
measurements.md#two-sinks-two-mode-behaviours, a section renamed to "Mode
behaviour by sink", and the link had read as fine ever since. Renaming a
heading is the ordinary edit that breaks these, so the check belongs where
the rename happens.

The rule resolves both forms the project writes: Markdown links, and the
bare docs/…md#section references the doc-comments use. Anchors match
GitHub's slug, so a repeated heading is reachable as -1 and an underscore
survives. Links inside a fence or a code span are examples and are left
alone, http and mailto targets are not fetched, and a full stop after a
bare reference ends the sentence rather than the anchor.

absPath in the file context was the display path, so it resolved against
whatever directory the process happened to be in. It is now what its name
says, taken from the root the run was given, which is also what let the
rule's own tests run against a temporary tree.
A metadata key cargo-deb does not support is dropped without a word. The
package would still build, still install on a clean card, and still pass
the install, remove and purge cycle — and fail only on the upgrade of a
card already running dex-loop, which is the one path this declaration
exists for and the one nothing here walks.

Same shape as the libmpv floor asserted above it, and for the same reason:
the field is invisible until the day it is missing.
Nine documents, two man pages and a glossary entry told a technician that
the card carries a FAT partition any computer opens, and that the three
files are edited with the card in a laptop. The package's postinst makes
/opt/dex an ordinary root-owned directory on the root filesystem, and the
card the guides build never gets a second partition — build-player-card
copies the files over SSH, which is the only route that works.

So the set described the intended card and called it the present one. A
technician planning the laptop route finds no such volume, and the page
that builds the card cannot tell them why.

What each document now says: /opt/dex is the assets directory, reached
over the network. The unit keeps RequiresMountsFor=, which costs nothing
against a directory on the root filesystem and is what lets a later card
put the assets on their own partition without touching the unit. The
partition itself is in the roadmap as the arrangement that is meant and
not built, and the glossary entry says so where it defines the term.
The card recipe sent the technician to a releases page to download the
package. No release workflow exists and no tag has been taken, so the page
is empty and the recipe stops on its own instructions. The crate README
already gave the route that works — the build artifact — and the guide now
gives it too, with the releases page named as planned.

Every shipped man page, and the changelog beside them, pointed at
dex-sidecar(1). The package installs neither that command nor its page, on
purpose: a video is prepared on a workstation. On a player both `man
dex-sidecar` and `dex-sidecar` fail. The references now say where the tool
runs, and the design page that had this right all along is left alone.
The manual page said mpv rounds @29.97 to 29, carrying the measured label
on a number that is not the measurement: the design page and the glossary
both say mpv matches on the nearest whole refresh, which is 30.

It also offered 2560x1440@60 as an equal alternative to auto for a 1440p
monitor, the value three other documents now record matching no mode and
restarting the player on a panel that offers 59.95 alone. And its entry
for the auto-mode warning still gave one outcome and one repair, where the
shipped message gives two of each.

The rotation advice was backwards in the place it mattered most. The
troubleshooting row said the rotation was dropped on the way out of the
container, then prescribed -noautorotate, which is the option that keeps
the pixels as stored — so a technician following the cure reproduced the
symptom. Both places now say what a .265 can hold, which route stores what,
and how to check the geometry before the video reaches a venue.
A step named for a plan code has been on every run's page since the
workflow landed, and its failure message carried the same code and a
retired word. The rules forbid both in anything a reader outside the
project sees, and a step name in the Actions UI is exactly that. The check
never caught it because the file was not among the paths CI passes.

It is now, which is what keeps this from coming back. The package name in
the conflict check is allowlisted the same way it is in the manifest: dpkg
reads a package name there, not prose.

Two descriptions of the check had also gone stale: the default path list
named a file the walk skips, and the CI paragraph still said the crate's
comments would join later. They joined.
Eleven places where two documents, or a document and the code, said
different things, and the reader had no way to tell which to believe.

The rules file put the exhibit config in /etc/dex, which dexd does not
read; it is the first text a writer consults. The front page said nothing
above 30 fps had been measured, four lines before citing the measured 4K60
result. The capability page stated a shipped limit on video size that no
code enforces and the front page denies. Both guides said `off` in the
heartbeat means the player never asked for that counter — dexd asks on
every start, and `off` is the branch where mpv turned the request down, so
the guides taught an operator to read a fault as a setting.

The rest are smaller and the same kind: a worked example dropping the
trailing D the paragraph is about, an example config naming the project's
capture card as the venue's display, a migration command that can leave
two configs where the same page says two make dexd refuse, a triage step
telling the reader to run a command the player does not have, another
restarting the show to read a version that prints without taking the
display, a claim that Rust removes leaks, and a manual page calling the
health check by a name nothing else uses.

Also: the reference now lists the two asset refusals and the watchdog
warning it had left to the design pages, while promising every message;
the packaging page describes the conflict fields the manifest gained; and
the REUSE file states what the setting is for instead of arguing for it.
The front page's next steps skipped the three pages that come next in the
only journey it describes — building the card, preparing the video,
writing the config — and jumped to troubleshooting, so a reader following
it arrived at the fixes before the recipe.

The developer walk had no ending either: nothing said what a change must
satisfy before it lands. The four commands now sit on the page that owns
the checks, pointing at the workflow for what runs when.

Also, four claims that carried a qualifier twice or an adverb where the
provenance label already stood, and the long-run scorecard, which reported
its own scoring rather than the result and left a "disagreement" whose
noun was not on the page.
The glossary fixes artwork as the whole installation and asset, or the
video, as the file. Four places said the artwork plays at the wrong size,
which reads as the installation misbehaving rather than one file being the
wrong geometry for the display. The warning message, its manual page entry
and the guide now agree with the entry.
Five findings a reader would have been stopped by, all of them written in
the last day while correcting earlier findings:

A repair that cannot be typed — "give the connector a forced mode with the
trailing D alone", where the grammar takes `none` or WxH@R[D] and nothing
else. A migration that fails in the case its own guard exists for: with a
config already in /opt/dex the move is skipped, /etc/dex stays non-empty,
and the rmdir errors with no next step. The one route to the package, a
build artifact, needs an account and expires after ninety days, which the
page did not say. A design page still claiming a 4K video plays scaled on
a 1080p monitor, which the measurement record now says it cannot. And a
manual page saying the frame rate cannot be read from the video, on a
project whose own tool reads it.

Then: two front doors stating as results what the measurement record calls
the player reporting on itself; a roadmap claiming players are not
networked, on a card the guides give SSH; two developer terms in a message
a technician reads in the log; a licence paragraph that covers the whole
clone, submodules included; a CI page claiming the check reads the
glossary, which every walk skips because it is the check's own input; one
observed monitor generalised into "many panels"; the long run's scorecard
using two words for one thing; and ten cells in the rules table that had
been shipping cut off mid-word.
The sweep that corrected nine documents and two man pages missed the
packaging manifest, the crate's own doc-comment and the systemd unit, each
of which still described /opt/dex as a partition a computer opens. The
unit's comment now says what RequiresMountsFor= actually buys: nothing
today, and a card that can move the assets to their own partition without
this file changing.

With them, the rest of the final read: two decode ratios a user guide
asked a reader to draw a conclusion from, "the exhibit" on its own where
the names table says exhibit config, Rust vocabulary on the download path,
the earlier package name used before the page says what it is, a counter
pair called "both" with no nouns, a flag named in a callout that no command
on the page carries, and a scope defended that nobody had attacked.

The CI comment and its error message lose the drama they had been written
with.
The correction that stopped the documentation calling /opt/dex a partition
went one step too far and wrote the idea off as unbuilt. dexOS ships a
third FAT partition today, mounted at /dexdata, on an image that plays with
pi_video_looper. What no dexd card has is the same arrangement at
/opt/dex, which is a directory on the root filesystem there.

The glossary entry and the roadmap now say which of the two is missing.

Also: the artifact caveat reaches the crate README, where the download
route is also documented, and both say the retention period is the
repository's setting rather than stating 90 days as a fact.
Both earlier versions of this paragraph were wrong. The original told the
reader to download dexd_<version>_arm64.deb from the releases page, which
has no dexd package on it. The correction then removed the releases page
entirely, on the strength of the roadmap's claim that no tag had been
taken — and the project has taken one: v1.0.0-rc.1, a 2024 pre-release
carrying a dexOS image and its build logs.

So the page is real, it is where dex releases live, and it is where dexd's
package will go. Until then the build artifact is the route, with what that
costs a reader stated: an account, and a retention period. The roadmap line
that started this now says which tag exists and that dexd has had no
release of its own.

Rule 17 makes the general case a rule, since the project is unfinished and
this is the second thing to go wrong the same way: say what is not built,
mark it (planned) or as a Note, and never write an intended arrangement in
the present tense.
Three places said the refresh rounding was measured on a Raspberry Pi 4,
and one sent the reader to the measurement record for the conditions. The
record holds neither the rounding nor the option-parser error beside it, so
a reader who followed the citation to check would find the page refuting
it.

The mechanism needs no measurement: a display mode carries a whole-number
refresh, mpv matches against that, so a decimal names the mode it is
nearest to. That is what the glossary's vrefresh entry already says, and
the three passages now say it too and point there. The option-parser
rejection keeps its error code as an observation against mpv 0.40, without
claiming a record entry that does not exist.

Found by auditing what this branch asserted about systems outside the
repository, after the releases-page mistake. The rounding was corrected
here yesterday from 29 to 30 — right by the mechanism, and resting on a
provenance nobody had checked.
V1 — the mpv core is unresponsive, not hung, which the retired-words table
forbids outright.

V2 — the build-identity entry drops the "(stamp file)" gloss rather than
tagging it; the filename says what it is.

V4 — the VBV entry said "dexd's artwork encodes", where the glossary's own
asset entry reserves artwork for the whole installation. The project's
video is what gets encoded.

V5 — sink stays and gains an entry, so the term the display world uses
keeps covering a monitor and a capture device at once, and the rule that
every term is either plain English or in the glossary stays true.

V7 — the sidecar page takes the name the table gives it: the sidecar
check. Two doc-comments pointed at its old heading; they point at the page
now, since an anchor to a page's own title says nothing extra.

V8 — layer stops meaning two things. The glossary's trio is described
without it, and the recovery ladder is four things in order. The stream
layer, the KMS layer, the test layers and the NAL layer are other domains
and keep the word.

V3 is deferred: Max is not settled on the name yet, so player card is left
as it stands rather than half-retired.
…ements

The word "master" was defined twice and differently, in a project whose own
field has settled names for these files. Time-based media conservation
distinguishes the artist's supplied master, the archival master and the
exhibition format — and the last of those is exactly what a dex card plays,
beside the exhibit config it is named by. Three entries now define them, and
the two pages that each invented a definition use the named one instead.

The word stays where the field puts it. DRM master is the kernel's term and
is unrelated; renaming it would make the pages disagree with the logs and
with upstream.

docs/README.md maps both sets of pages, which the design side had no way
into or out of: a technician's six guides in order, and the thirteen design
pages grouped by what they answer. Linked from both READMEs. The guides keep
their own Related pages lists; the design pages get their signpost here
rather than thirteen new tails.

The measurement record gains the two readings that were cited from other
pages and never recorded: the shared-object count of the installed binary,
and the END_FILE that a loadfile replace produces, which is the event the
whole in-place recovery rests on absorbing. Both pages now link the record,
which is what a measured value is asked to do.
Setting a player up should be choosing dexOS in Raspberry Pi Imager, the way
any other operating system is chosen. The guide is renamed to say so, and
the roadmap's Distribution section carries the path.

The image that would make it true is not built, so the page says that in a
note and keeps the manual steps: Raspberry Pi OS Lite, then the package on
top. Those steps do not expire when the image ships — running dexd on a
system someone chose themselves stays supported, and these are the steps
for it.

dexOS ships in two lines, which the glossary now states: the buster one that
drives HD on older boards with the legacy player, and a trixie one carrying
dexd for 4K on a Raspberry Pi 4 or later. Rebasing the first onto the second
stays rejected in Alternatives, because that would migrate working 1080p
installations; two lines is the plan and always was.

A dex card is any card that boots a Pi into a player; one built from the
image is a dexOS card. player card is tagged retired, and the allowlist
entry that existed only because the old filename contained it is gone.

The roadmap's own "Exhibition format" section is renamed to Playlist
format. It described a playlist with per-video transforms, which is not what
time-based media conservation means by the term, and the glossary now
carries the conservation sense.
Two blind spots, one in each direction.

A step name is printed on every run's page and an annotation reaches
whoever reads a failed build, but the extractor treated every YAML value as
data, so neither was ever scanned. That is where a plan code sat unnoticed
until a reader found it by eye. The file's own name:, each step's - name:
and the text of an ::error::, ::warning:: or ::notice:: command are prose
now; a name: indented under another key is an artifact or an input and
stays an identifier. Turning it on immediately found a retired word in a
shipped error message, which is fixed here.

The other way: a docs/…md#section reference is a path, and its file name
and heading slug are made of words nobody wrote as prose. Renaming a
heading to "the sidecar check" reported the retired command name its slug
contains, and a guide's file name reported whatever the guide is called —
which is what the allowlist entry deleted with the rename had been holding
back. Paths are blanked out of prose everywhere but Markdown; the links
rule reads the raw line and still resolves them.

Four tests: the three name shapes and the annotation, the nested name: that
must stay data, the shell past an annotation's closing quote, and a slug
that no prose rule may read while its link still resolves.
The roadmap closed a read-only root filesystem as something the project
ships, on the evidence that installations survive being switched off at the
socket without one. That decision stands. What has changed is that a
deployed card now runs with the overlay filesystem switched on by hand and
its boot partition write-protected — one operator's hardening rather than
anything dexd sets up, and safe there because that card's video never
changes.

The consequence belongs in the guide, because it is silent: on a read-only
root the exhibit config is written to the overlay, looks applied, and is
gone at the next boot, with the player still running what it had. Turn the
overlay off, edit, turn it back on.
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