Commit Graph
10 Commits
Author SHA1 Message Date
John O'Keefe aee1aafc74 docs(admin): hash conflicts page — the duplicate-content queue
Sixth admin page. Documents what creates conflict groups (scanner at
scan time + the hash backfill retroactively), the group card anatomy
(count badge, library + short SHA-256, per-copy rows with usage summary
highlighted when that copy holds reading data), and both resolutions
with verified semantics: Keep this copy (reparents the other copies'
children into the kept copy, deletes their catalog rows, records the
resolver — files on disk never touched, consistent with platform-wide
delete semantics) and Keep both (mark resolved, stop flagging, nothing
merged). Glossary gains Keep both and Keep this copy.
2026-11-02 14:12:10 -05:00
John O'Keefe 3e55ddd88a docs(admin): libraries page — the definition surface, with backlinks
Fifth admin page and the section's hub. Documents library creation
(name/description/type — type fixed at creation, verified in the edit
modal), the card's Force Rescan + Manage controls, and the full panel:
folders (add via Browse or manual path, shallow per-folder scan,
removal-unregisters-only semantics verified in DeleteLibraryFolder —
files and items untouched, archive lifecycle governs the rest; podcast
roots refuse hand scans), User Access visibility checkboxes (default-
allow, DB-enforced), the processing-issues link, and Delete Library's
exact destructive scope (records + reading data gone, files on disk
untouched). Ends with the at-a-glance scan table linking scanning.md.
Adds the Libraries backlinks to the processing-issues and archived
pages. Glossary gains Create Library, Manage, Edit Details, Delete
Library, View Archived, Purge Archived Now, Browse, User Access.
2026-11-02 14:11:25 -05:00
John O'Keefe ecb6a7385a docs(admin): archived items page — the missing-file lifecycle
Fourth admin page. Documents the two-consecutive-scans archive rule,
the history-preserving rationale, ARCHIVE_RETENTION_DAYS (default 90,
0 = manual-purge-only, verified in config.go), and the four actions with
verified semantics: Merge (progress/annotations/collections folded into
the active copy, per-user collisions keep the active copy — mirrors
hash-conflict resolution), Restore (immediate; re-archives if the file
is truly still gone), Delete (item + history, permanent), Purge All
Archived (the clean-slate button, confirm text quoted). Links to
scanning.md for why only library-wide scans archive. Glossary gains
Purge All Archived, Merge, and a scoped generic Delete entry.
2026-11-02 14:10:16 -05:00
John O'Keefe 88e3de606c docs(admin): processing issues page — per-library scan-failure ledger
Third admin page. Documents the severity stat cards (errors/warnings/
info, cards only appear when non-zero), the per-issue card fields, and
the three actions with their real semantics: Retry (per-item scanner
re-run — success closes the issue, failure surfaces the real error),
Retry all (sequential queue with done/total progress, deliberately not
a library-wide scan), Dismiss (warnings/info only, confirm-guarded;
errors cannot be dismissed). Links to scanning.md for the retry-vs-
library-scan distinction. Glossary gains Retry, Retry all, Dismiss.
2026-11-02 14:09:34 -05:00
John O'Keefe b3a8cbd582 fix(admin): library row button renamed 'Scan' -> 'Force Rescan', per owner
Owner ruling that closed the scan-semantics discussion: the code is
correct (per-library scan IS a force scan — hx-vals force:true since
706be09d), but the label hid that. Now the naming invariant holds
everywhere: anything with Force/Rescan in its name re-reads everything
in its scope; plain 'Scan' only exists at folder scope ('Scan this
folder', shallow) and in auto mode. Book-level Rescan verified as the
per-item force path (extractMetadata re-reads sidecars/tags regardless
of file size; recomputeHashInfo follows) — it is the documented answer
to 'I changed this book's sidecar'.

Glossary Scan entry replaced with Force Rescan (old label kept in also:),
scanning.md table + prose pick up the new label. Generated file
regenerated with the Dockerfile-pinned templ version from inside
templates/ so the diff is exactly the label strings.
2026-11-02 14:08:19 -05:00
John O'Keefe 89fc479bdb docs(admin): scanning page — the shallow vs. force taxonomy from source
First page of the admin tree, written to the new admin tier (what the
click actually does). Documents every scan surface with its verified
semantics: Force Rescan All Libraries (dashboard, force, all libraries,
one job each with skip-on-active), the per-library Scan button (ALSO a
force scan — hx-vals force:true since the button's birth commit 706be09d,
which corrects the owner's stated 'other scan buttons are shallow'
belief; flagged to the owner), Scan this folder (shallow, single-folder
scope, archive pass skipped for partial scans, podcast roots refused),
Auto-Scan + Scan Interval (the watcher + poll + startup triggers, all
shallow, default 60s range 1-3600), Processing Issues retry (per-item
sequential, deliberately not a library scan), and book-level Rescan /
Reset to Scanned. Plus the standing rules: one scan per library
(coalescing), background jobs with the dashboard progress panel, and
the two-consecutive-scans archive rule.

Glossary gains Scan and Scan this folder (same-commit rule for controls
cited in prose). The real-tree nav test's Administration assertion now
pins shape (Admin Guide, Libraries prefix + usabilityOrder subsequence)
instead of an exact slice, so pages landing one at a time don't churn it.
2026-11-02 13:47:40 -05:00
John O'Keefe bb141cdffc fix(admin): rename 'Scan All Libraries' to 'Force Rescan All Libraries'
Owner: the dashboard button's label under-promised what it does. The
action is a FORCE rescan (scanner.SetForce(true) via the scan worker):
every file re-read and re-extracted with original-scan semantics, hash
identifiers recomputed — the admin's backfill tool, per the scanner's
own source comments. The shallow scans (per-library button, per-folder
scan, processing-issues retry) deliberately skip unchanged files and
keep their 'Scan' labels; the naming now carries that distinction.

Subtitle updated to state the real semantics ('Re-reads every file and
re-extracts metadata and hashes — slow but thorough') instead of the
old 'Re-scan existing files and detect new items', which described the
shallow path. ui-controls.md gains the canonical glossary entry (old
label recorded under also: so anything still quoting it resolves); no
doc quoted the old label yet, so no doc edits were needed.
2026-11-02 13:39:52 -05:00
John O'Keefe c1a7648076 docs(user): reader audio section + kobo guide refresh to platform reality
reader-guide.md gains the audiobook/episode player section (seek,
prev/next episode, Bookmarks panel, Chapters list, Player settings with
autoplay/speed/resume-rewind overrides, Shortcuts dialog) — the player
existed with zero user docs.

kobo-setup.md drops the stale 'not available yet, actively being
developed' framing: the server side of native Kobo sync is implemented
and documented (sync/initialization endpoints, bookmark + markup sync,
shelf mappings, KEPUB sidecar config), so the guide now states exactly
that, keeps stock-firmware rollout as the honest remaining piece, and
keeps KOReader as the supported today-path.

ui-controls.md: Player settings / Shortcuts & interactions / Chapters /
Bookmarks entries (templ-entity fragments for ampersand labels).
2026-11-02 10:09:18 -05:00
John O'Keefe 9e2f216af5 docs(user): dashboard, browsing, profile rewrites + new podcasts guide; trash stubs
Ground-truthed against the templates this pass:
- dashboard.md: real section kinds (system shelves incl. Continue
  Series, user collections, custom sections via /custom-section
  builder), Customize Dashboard panel semantics (per-library, drag,
  switches, 10-50 items, Save Changes), Refresh, This Week widget,
  per-item Read/Listen and progress-conflict resolve actions. The old
  page listed a wrong shelf set and never mentioned custom sections.
- library-browsing.md: the file was secretly titled 'Saving Custom
  Filters' and covered nothing else. Now the browsing page: All Books
  toolbar (search, Sort, Filters -> drawer hand-off, Save/Load/Clear
  saved filters), book detail as hub, series pages, podcasts split.
- profile-guide.md: field table ground-truthed from profile_form.templ
  (username/email DO remain editable there), audio defaults (speed,
  resume rewind, keep awake), timezone rendering contract, both theme
  doors (7-pick select vs 37-theme Appearance panel), Change Password
  with live checks, Danger Zone/Remove My Account + last-admin rule.
- podcasts.md NEW: the Podcasts page had zero documentation. Subscribing
  (Add Feed -> RSS URL, library, back-catalog download, download order,
  Add & Subscribe), Continue/All Feeds, Download All, player + Play as
  Sequence cross-link.
- Trashed user-areas.md, frontend-guide.md, settings-guide.md: stubs
  whose planned content now exists as real pages (or duplicates
  profile-guide). user-guide.md rewritten as the plain-language front
  door with a go-here-when table; index.md rows updated to match.
- ui-controls.md: 10 new gate-checked entries for every newly cited
  control (Add & Subscribe via templ-entity fragment).
2026-11-02 10:07:28 -05:00
John O'Keefe e07301f74a docs(standard): screenshot-free UI documentation standard + UI-label gate
The planned Playwright screenshot docs (SCREENSHOT_AUTOMATION.md) are
replaced by a text standard: screenshots rot silently and cannot be
gate-checked, while this UI's labels are server-rendered templ literals
that can. Layers: pattern-first prose (concepts survive redesigns) >
capability inventory > label->outcome flows > quoted labels > generated
references where a registry exists (filters/fields.md precedent). The
filter docs stay hands-off exemplars; user-doc tone is plain language by
contract, dev/admin tone explicitly deferred.

writing-ui-docs.md is the standard (page template, findability notes,
tone-by-audience, process rule: a UI change is not done until the docs
audit runs). ui-controls.md is the canonical control-label glossary the
docs quote from; TestUIControlLabels greps every entry against
templates/*.templ (source: ts override; also:-fragments for
Alpine-composed labels like the Match/Group header) so renames fail
make test in the same commit as the rename. Gate proven both ways: a
planted bogus label failed; restored set passes.
2026-11-02 08:18:19 -05:00