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>..HEADin 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.wikiblocked.**§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.mdfirst, and then this branch shipped spec 28's phases A and B — so the roadmap listed image search at0/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_imagesreaches 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.