Skip to content

v0.80.0 — the ledger

The roadmap and the specs it points at had drifted apart, and every planning conversation was paying for it. Nine inconsistencies, found by reading all fourteen docs/committed/ projects against CHANGELOG.md, git tags and modules.hosted.json: releases that shipped untagged, projects that finished and were never retired, forty-four tasks marked [ ] that shipped two releases ago, a spec header naming two release numbers that were both wrong, and ten projects the roadmap did not mention at all.

None of it is a bug a user can see. All of it is why the answer to "what is next, and what is it waiting on?" took a day to reconstruct.

The plan

  • [x] L.1 — ROADMAP.md. The plan for what has not shipped, as its own file at the repo root: every release in order with what it is waiting on, the dependency chain from Library back through the legal documents to project 6, the decisions that are yours, and an index of all fourteen projects. CHANGELOG.md's Roadmap section becomes a pointer — two roadmaps is how this drift started.

  • [x] L.2 — Retro-tag the four untagged releases. v0.74.0, v0.76.0, v0.77.0 and v0.78.0 all shipped without tags; 0.76.0 and 0.77.0 landed inside v0.78.0's squash and never got a merge commit of their own. Tags are how git log <reviewed_at>..HEAD in v0.81.0's staleness check finds anything.

    v0.74.0 tags its own merge commit. The other three **all point at
    `525d91e7`**, because that is the truth: one squash shipped all of them and
    none has a commit of its own. `git describe` is ambiguous across those
    three as a result, and a staleness query bounded by any of them returns the
    same range — which is accurate rather than convenient. The tag messages say
    so. Tag history is contiguous from v0.73.0 to v0.79.0 now.
    
  • [x] L.3 — Retire the three finished projects. 14-playtest-issues (shipped v0.58.0), 24-chat-log-compactness (v0.73.0) and 25-system8-build-time-ingestion (v0.76.0) are complete and still filed under docs/committed/. 25's index still reads "Nothing is built" over a §9 recording four shipped phases.

  • [x] L.4 — Tick what shipped. Library phases 0–2 (24 tasks) and Image Manipulation phases 0–2 (20 tasks) are [ ] in their specs and shipped in v0.66.0 and v0.70.0. Fix 17's index header with them: it dates phases 3–4 to v0.71.0 and 5–6 to v0.72.0, and neither is true.

    Both status headers are rewritten to say which phases shipped where, which
    are gated and on what, and how many tasks are left — 24 of 39 for Library,
    34 of 51 for Image Manipulation. A spec's header is the first thing anyone
    reads and was the last thing anyone updated.
    
  • [x] L.5 — Close 11-impersonated-token-context. CS-15.10 (contract tests), CS-15.11 (Module API bump + docs), CS-15.12 (retire the components CS-15.5 found dead). Ten of thirteen done since v0.57.0.

    **CS-15.11 was overdue rather than new.** All four members it was going to
    version — `getTokenAttributes`, `getTokenTraits`, `getTokenIdentity`,
    `DerivedStatPanel.computeForToken` — shipped in v0.57.0 and were never
    given a number, and both `dnd5e` and `system5` have implemented them since
    that same release. So there was nothing to publish and nothing to re-pin;
    what was missing was the declaration. **1.35.0** is it, plus a module-author
    section on the four rules that govern them.
    
    **CS-15.12 is deferred, and the estimate in the spec is wrong.** It reads
    as "~30 files and ~10 comments". The deletions are right, but deleting
    `PlayModeView.tsx` also breaks **fifteen source-text guards that
    `readFileSync` it and assert against its contents** — each needing a
    judgement about whether the assertion still means anything against the
    sheet that replaced it, or dies with the file. That is the work, and it is
    not a tidy-up. See ROADMAP.md.
    
  • [x] L.6 — Close the two v0.76.0 leftovers. 25 §4.3, the beta pill in Admin ▸ Systems, and §3.3, verifying a full sheet renders with system8.purplecat.wiki blocked.

    **§4.3 was already built** — `AdminSystems.tsx` has rendered an orange
    `beta` badge on `channel === 'beta'` since v0.76.0. The task was never
    ticked, which is the same defect as L.4 in miniature.
    
    **§3.3 gets a guard, and the guard found something better than expected.**
    De-allowlisting the host proves nothing about a call that never went
    through the proxy — precisely the bug v0.76.0 found late, where
    `derivePowerActions` reached the wiki through bare `fetch()`. So the new
    guard pins what an allowlist cannot: the host may be named only where a
    *person* is being sent to a page. **Exactly one file in the platform names
    it in code** — `SystemContext.tsx`'s fallback URL for the Help iframe.
    Everything else that mentions it does so in a comment recording where
    content used to come from.
    
    Writing that guard reproduced the repo's own favourite bug: a naive
    `//.*$` comment stripper ate `https://` out of every URL, so the first
    version reported that nothing names the host and passed vacuously. The
    `[^:]` guard against that is commented in place.
    
    §7.3's other half — the Reload button's copy — now says outright that it
    does not fetch rules content. The dialogue described what it *does*
    accurately and never addressed what a reader would assume it does.
    
    What is **not** closed is the live check: a full System 8 sheet rendered
    with the host actually blocked needs a real campaign and a real character,
    and stays a manual step.
    
  • [x] L.7 — Rewrite the v0.75.0 playtest backlog into tasks, so v0.82.0 can build it rather than re-read twenty-three notes.

    Twenty notes became **P.1–P.18**, grouped by what they are rather than by
    the order they were typed. Two findings the rewrite produced: three of them
    are System 8 *content* problems and cannot be fixed in this repo, and
    **P.2 and P.3 contradict each other** — one wants typeaheads to advertise
    themselves, the other wants the class dropdown to stop being one. That is a
    rule to decide, not two tickets to close.
    
  • [x] L.8 — File the Create Token modal ask as 29-create-token-modal — 10 tasks, 4 decisions. Two things the write-up surfaced that the ask did not: CC BY 3.0 wants the individual artist named per icon rather than a blanket credit, so the attributions page is generated from a manifest and guarded; and the tooltip the ask moves the description into does not exist on touch, which is where this modal is opened from a map.

  • [x] L.9 — The ledger records its own release. L.1 wrote ROADMAP.md first, and then this branch shipped spec 28's phases A and B — so the roadmap listed image search at 0/14, described the consolidation that had already happened as phase one still to do, and carried the project's one hard date (1 January 2027) nowhere at all. That is L.4's defect, six commits old, in the file written to prevent it.

    Also retired: the "duplicated work" note that `CHANGELOG.md`'s Phase 2
    list tracked project 12 twice. L.1 fixed it by moving the list; the note
    survived the fix and read as outstanding.
    

Misc

  • [x] When using the streaming chat API, the message appears minimized by default. It should be expanded by default. (Sometimes they appear to collapse only after rolls complete. In any case, minimize is a user-initiated action, it shouldn't ever happen on its own)

Larger features — specs written, two of three unbuilt

Each is now a spec under docs/committed/, with atomic tasks and the decisions that block them. Upsampling and background-token resize are unimplemented here. Image search is the exception, and the reason is its deadline rather than its priority.

  • Add upsampling to the Retouch menu for all images (2x, 3x, maybe 4x if possible) → 26-retouch-upsampling. The upscaler already exists and already does 2×/3×/4×; production pins a genai that predates it, the Retouch dialogue has no way to ask for a factor (so every run is 2×), and an upscale currently resizes the map token it came from.
  • Add Resize option to the selected background token UI: easily double, triple, or quadruple size of the token on the map, preserving aspect ratio, pinning to center (default) or 8 other positions on 3x3 grid → 27-background-token-resize. Map geometry, not an image operation. Four of the nine anchors already exist inside the corner-drag resize; the whole feature is one pure function and a 3×3 picker.
  • Add Bing option for token art image search → 28-image-search-providers, and it stopped being an option to add. Google's Custom Search JSON API — what every image search in the app runs on — is closed to new customers, and existing customers must be off it by 1 January 2027. Its 10,000/day cap was never raisable, there is no business tier, and Google's named successor (Vertex AI Search) does not do open-web image search. So this is the replacement of a search backend with a shutdown date, which delivers the asked-for second index on the way: Bing has no first-party API either, and SerpApi's bing_images reaches it — plus Yahoo and Yandex — on one credential, with no cap and no dependence on the retiring API. Phases A and B shipped in this release; C (the SerpApi route) and E (a per-user quota, and moving Google's published key server-side) have a deadline.