Skip to content

v0.82.0 — Playtest & polish

The highest user-visible value per hour in the backlog, and no decisions in it. All eighteen items from the v0.75.0 playtest, written up as tasks by v0.80.0 and kept here rather than copied: they are ticked where they are.

Two of them were already fixed. P.16's plant powers resolve every action document in the shipped bundle — 517 references were checked and the only four that dangle are ones the ingestion spec already records — so v0.76.0's slug-vs-name correction was the cause, exactly as this entry predicted. And stroke/fill editing of a selected shape has worked since the drawings work. What shipped instead of a fix, in both cases, is the check that would have said so in one line: a power that cannot resolve its actions renders as a power with no actions, which is precisely what a power with no actions looks like.

Four fixes turned out to be one fix each in a shared place, which is what the playtest was really reporting:

  • P.2 and P.3 read as opposites — nothing signals a typeahead, and the class dropdown should not be one — and are the same defect: searchable was a per-call-site taste decision. It is a property of the option list now.
  • P.10's share dropdown leaves the viewport because Mantine's flip and shift cannot help a popup taller than the space in both directions. Every dropdown in the app is clamped.
  • P.13's clipped labels are a Mantine default: overflow: hidden on the button root and nothing on the label, so a long label is guillotined with no ellipsis. Every button in the app now ellipsises.
  • P.14's alert icon is "not red" because the severity map named raw Mantine colours, and the retro skin re-points blue at walnut. Both skins gained the warning family a three-step severity scale needs.

Riding along: the Create Token modal — create-token-modal, all 10 tasks. Eleven full-width text rows became a two-column grid of illustrated cards. The two things to get right rather than fast were got right: CC BY 3.0 requires naming the individual artist per icon — Game-icons.net is many artists, and book-cover exists twice upstream under different ones — so the attributions page is generated from a manifest and two --checks fail the build when the manifest, the vendored files and the page disagree; and the tooltip it leans on does not exist on touch, which is where this modal is opened from, so D2 is answered by input rather than by width and the description renders inline where there is no pointer.

Three System 8 items, and only one was a content problem. P.16 was not. P.17's orphan pass was real and is done in the docs repo (37 pages deleted, 10 relinked, three silent content bugs found beside them); the platform half was re-ingesting it, because the bundle is a build artifact and the build had not been run for two releases. P.18 asked about a rank powers do not have: it was an action's name, and a character-rank gate written in three different places at once. Seventeen actions declare minRank now — the field the platform has read since v0.78.0 and which no document had ever declared.

Module releases this cut: system8 0.16.0 (platform-side) and system8 8.17.0 (the docs repo).

Onboarding — the sheet does not teach itself

The through-line of the session: a first-time user found the features by accident or not at all. Each of these is one affordance, not a tutorial.

  • [x] P.1 — Add Class is easy to miss. ("add class easily missed") Find what the control looks like at rest on an empty sheet and give it the weight of a primary action. A character with no class is the one state where this cannot be a quiet icon.
  • [x] P.2 — Nothing signals that a field is a typeahead. ("doesn't know about typeaheads") Six searchable Selects on the sheet look exactly like plain dropdowns until you type into one. Either show the affordance (a search icon, a "type to filter" placeholder) or stop making them searchable — see P.3, which wants the opposite for one of them.
  • [x] P.3 — The class dropdown should not be typeable. ("class/level selector's class dropdown is typeable...should be a regular dropdown") A closed vocabulary short enough to read has nothing to search. Note this pulls against P.2: the fix is consistency about which selects are searchable, not a rule for all six.
  • [x] P.4 — Generate Ability Scores goes unclicked. ("didn't think to click Generate Ability Scores (need a wizard)") The note asks for a wizard. Read it against the Character Sheet Overhaul first — a previous ability-score wizard was scrapped deliberately, and reintroducing one needs to answer why this time is different. The cheaper reading is that an empty ability block should offer the action rather than waiting to be discovered.

Powers, and the filter dialogue

  • [x] P.5 — Users browse powers without filtering, sorting or searching. ("browsed powers without filtering, changing sort, etc") The symptom of P.6; worth confirming the controls are visible before redesigning them.
  • [x] P.6 — The filter dialogue needs a rework. ("filter dialog sucks") The one note with no specifics, and the one that shows up three times. Needs a design pass, not a fix — treat P.7 and P.8 as its acceptance criteria.
  • [x] P.7 — Filters must combine within a facet. ("used multiple classes for power filter, multiple schools at the same time") Multi-select per facet, OR within a facet and AND across them. A user who tried it expected it to work.
  • [x] P.8 — "Current filters" eats the modal on mobile. ("current filters is taking up most of the filter modal on mobile") The summary of what is selected should not out-size the controls for selecting it.

Layout and mobile

  • [x] P.9 — The top of the character sheet sits under the fixed header. Scroll-margin or padding on the scroll container. The sheet is the scroller — do not wrap it in a ScrollArea (v0.48.0).
  • [x] P.10 — The share dropdown leaves the viewport in mobile landscape. A short viewport with a bottom-anchored trigger; the popover needs flip or a viewport clamp.
  • [x] P.11 — Ability-score +/− buttons run off the page on mobile. On some scores, so the cause is a width that depends on the label.
  • [x] P.12 — Numeric steppers should put +/− on the left and right, flanking the value rather than stacking. Related to P.11 and probably the same component.
  • [x] P.13 — Button labels are clipped in the edit-artwork modal in portrait. ("can't quite see all the labels") — clipped, not wrapped, which points at a fixed width rather than a flex problem.

Small, specific

  • [x] P.14 — The section alert icon is not red. Noted as "section-specific", so the colour is right somewhere and wrong on the section header. v0.36.0's semantic colours are the vocabulary to fix it in.

  • [x] P.15 — The new-attack flow lets you skip the type. The note wonders whether the picker should be graphical. Decide whether type is required before deciding how it is chosen.

    **Required, and the fix is in the module** — `system8` 0.16.0, since CS-9
    moved the attack editor there and the platform deliberately offers no
    generic fallback. It did not let you skip the type so much as fill it in:
    the field defaulted to `Weapon`, and a default is skipped by not looking
    at it. `isImplement` is what decides whether an attack has a damage
    weight at all, so a defaulted Weapon where the player meant a Spellcasting
    Implement keeps a weight that attack must not have — the wrong shape, not
    a wrong number, and it looks complete. Not graphical: four options whose
    difference is a rules category are not clarified by four pictures.
    

System 8 — two of these are not content problems

Investigated 2026-09-07 while writing them up, because the first draft of this section asserted a cause for P.16 that turned out to be wrong. Recorded here so v0.82.0 does not start from the same guess.

  • [x] P.16 — Plant Shape and Plant Growth show no actions. Re-test before touching anything. The first reading was that this is the dangling action-reference defect System 8 build-time ingestion records for four psion powers. It is not: all nine action documents both powers reference exist in the docs repo, both powers are in data/powers.json with their actions arrays intact, and all nine documents are in the bundle's docs-index.json.

    **The likeliest answer is that v0.76.0 already fixed it.** This playtest
    ran against v0.75.0. v0.76.0 found that `characterToToken` matched a
    character's power against the record's `name` when that field held a
    *slug*, so "every lookup would have missed, and every power would have lost
    its action URLs and its subcategories" — which is this symptom exactly.
    Reproduce on current `main` first; if it survives, it is a platform bug and
    not a content one.
    
    **Re-tested 2026-09-09 against the shipped bundle: it does not
    reproduce.** Both powers carry their `actions` — two on Plant Shape,
    seven on Plant Growth — and all nine resolve to documents the bundle
    holds. Every action reference in the whole corpus was resolved the way
    the platform resolves one: **517 references, 4 dangling**, and those four
    are precisely the psion powers
    System 8 build-time ingestion
    already records. Neither plant power is among them. So the cause was
    v0.76.0's slug-vs-name correction, as this entry predicted, and there is
    nothing left to fix.
    
    **What shipped instead is the check that would have said so in one
    line.** The reason this took three passes is that a power which cannot
    resolve its action documents does not error — it renders as a power with
    no actions, which is what a power with no actions looks like. The module
    already asserted that every record's own `url` resolves; it now asserts
    the same of every `actions` reference, with the four known danglers as a
    named allowlist so a fifth fails the build and those four stay visible
    rather than becoming a silent baseline. The platform half is pinned too:
    `toSystemPower` is the adapter the v0.76.0 defect lived in, and it now
    has to keep `actions`, the url they are relative to, and the display
    name rather than a slug.
    
  • [x] P.17 — An orphaned-power pass. ("system8 needs an orphaned power pass") Real, and the tooling now exists: scripts/find-orphans.mjs in the docs repo walks the link graph forward from the pages a reader can reach. It currently reports 47 orphans, 40 of them witch action pages — which is a single rewrite's worth of debris rather than forty separate mistakes, and should be read that way before anything is deleted.

    **Done in the docs repo as `system8` 8.16.2**, and read exactly that way:
    the corpus is at zero, split between deletion and relinking rather than a
    blanket `--apply`. 37 deleted as genuine debris — 30 witch action pages
    superseded by 8.6.0's rewrite, three files whose contents were the text
    "delete me", a zero-byte file, and three drafts of abilities later
    replaced. 10 were *live content missing from an index* and were linked
    rather than removed. Three silent content bugs surfaced beside it.
    
    **The platform half is the re-ingest.** None of that had reached the app:
    the bundle is a build artifact and the build had not been run since
    8.15.0. `system8` 0.16.0 rebuilds it from 8.17.0, which brings the orphan
    pass and the Wings of Freedom action fix with it.
    
  • [x] P.18 — Spores is rank 2. ("spores is rank 2? wtf?") A power has no rank. Neither spores.md's frontmatter nor its data/powers.json record carries one, and system8 0.15.0 restated the rule: a character has a rank derived from level and may take any trait at or below it; slots have no rank. So this is either a rank the sheet is deriving and displaying, or the reader seeing the action rapport-spores-rank-2 and reading its name as the power's. Establish which before writing a content fix.

    **Established: the second.** The sheet derives no rank for a power. The
    action's `name:` was literally `Rapport Spores (Rank 2)`, and it renders
    under the power it belongs to.
    
    **The rank is real and worth keeping** — it is a *character*-rank gate on
    the action — so the fix is to move it out of the name rather than delete
    it. It was being written in three places at once: in the `name:` of three
    actions, as a `(Rank N)` prose prefix on twelve more, and, for four
    others, only in the summary table of the power that lists them, with
    nothing on their own page. None of it machine-readable.
    
    **`minRank` is the field, and it already existed.** The platform has
    parsed it off an action document since v0.78.0 (E.1), which added it for
    exactly this case and recorded that no document declared one yet.
    Seventeen do now (`system8` 8.17.0), no action's name carries a rank, and
    the derived action shows "Requires rank N" ahead of its other metadata —
    through the same `parseMinRank` that fills `IAction.minRank`, so the line
    shown and the field carried cannot disagree. Displayed, not enforced,
    which is v0.78.0's standing decision.
    
    Polymorph is deliberately untouched: its ranks are per-effect, not a gate
    on the action. And `fungal-bastion.md` turned out to be **two documents
    in one file**, the second behind a `<!-- filename: … -->` comment — a
    split written down and never performed, so the rank-2 Fungal Bastion
    existed in the docs repo and nowhere else.
    

Riding along

  • [x] The Create Token modal, all 10 tasks — create-token-modal.
  • [x] TODO.md: a power action's wikilink. The link was right; opening it was wrong. The system sidebar's follow-the-system effect also ran on mount, so it replaced the clicked URL with the system's home page — you clicked an action and arrived at the front of the wiki. Beside it, whether a link opened in the sidebar at all was a hardcoded purplecat.wiki substring, so a self-hoster's link left the app.
  • [x] TODO.md: token props transfer back to the character. A property definition declares its scope. token is the default and every existing definition means it, so nothing changed until one opts in; character makes an edit on a linked token write the character, so the value reaches the sheet and every sibling token. Not a blanket write-back: two tokens can belong to one character — a summon, a mirror image — and a shared HP pool would be a bug.
  • [x] TODO.md: stroke and fill on a selected shape. Already worked; verified and left alone.
  • [ ] TODO.md: non-power actions have no wikilink. Investigated: there is nothing to link. Attacks, skills, ability checks and defensive reactions are derived from the character rather than from a document, and System 8 publishes no page for any of them. Building a link would be building a 404. It becomes possible if the system ever publishes per-skill or per-reaction pages.