diff --git a/documentation/audits/app-guides-2026-10-15/TASK.md b/documentation/audits/app-guides-2026-10-15/TASK.md new file mode 100644 index 00000000..96bbb948 --- /dev/null +++ b/documentation/audits/app-guides-2026-10-15/TASK.md @@ -0,0 +1,400 @@ +# Night task: app user guides — gate, media pilot, then every other app + +> Saved verbatim from the operator's message of 2026-10-15 ~21:50 CEST. The spec (the APPENDIX) existed +> nowhere on disk; this file is the record. The brief above the appendix wins where the two differ. + +## For the operator (plain language) + +Tonight Claude Code writes a user guide and an FAQ for every app in the catalog, in Hungarian and English. +It starts with the five media apps, then does the other 60. Each guide is checked against the app's own +source code at the exact version we ship. A guide that fails the check stays hidden. It only adds text to +the catalog. Old boxes ignore the text, and boxes on 0.315.0 or newer show it on the „Útmutató" tab. + +In the morning: read the Plex and the Sonarr guide on demo-hp. If you want the format changed, it is one +pass over all files. + +--- + +## What to run + +Run **the full spec in the APPENDIX at the end of this message** (Part 0 → A → C → B → N). It is the spec. +It is not on disk anywhere — this message is the only copy. Save it as +`felhom.eu/documentation/audits/app-guides-2026-10-15/TASK.md` in your first docs commit, so the record exists. +The part above the appendix states what changed since the spec was written and the night rules. Where they +differ, the part above wins. + +**The pilot has not run yet.** At 21:45 CEST the catalog `main` is still `e67aad49`: no gate change, no guide. + +## 1. Baselines (re-read at start; do not trust) + +| Repo | `main` @ | Note | +|---|---|---| +| app-catalog-felhom.eu | `e67aad49` | the repo this task changes | +| felhom-controller | `e7b64af1` (v0.317.0) | read only. Guide schema as built: `internal/stacks/metadata.go` `AppGuide` (~L171–L200: `checked_version`, `sections[].title/intro/steps`, `faq[].q/a`), overlay in `metadata_i18n.go` (~L73–L104). It matches the spec's Part 5. | +| felhom.eu | `371b72da` | docs, register, STATUS only | + +demo-hp guest 9201 runs controller **0.317.0** — it renders guides. + +## 2. Night rules + +1. **Unattended.** Ask nothing. Take the most reasonable reading, write it at the top of the report, go on. +2. **demo-hp is shared tonight** (other sessions may be building or testing on it). For the pilot's box + check (Part A.3): use only media apps **already running** on 9201, **read only** — API reads and page + fetches, no install, no remove, no restart, no setting change, no Plex claim. An app that is not running + there gets the label check only; set `checked_version` by the spec's §8 label-check row and list it in + the report as „box check owed". Tester 1, N100, ep0, DooPlex: not touched (DooPlex runs your git and + reads only). +3. **The rendering check** goes through the public address: `https://felhom.enkisfelhom.hu/apps/sonarr/guide` + (and plex) after the catalog sync reaches 9201. Log in the way the earlier sessions did (password stored + out-of-band, never printed). Assert the `data-guide-section` count; save a screenshot if a browser is at + hand. If the sync has not arrived by the end, say so — do not force it. +4. **Push in batches** of about 10 apps, gates green before each push. Before every push in any repo: + `git pull --rebase`; other sessions push tonight. Never force-push. Never `--no-verify`. No branches. +5. **Time.** If the night runs out, stop at a pushed batch boundary. The report lists the apps done, hidden + (and why), and not started. Never leave a half-written template on `main`. +6. **One format.** Keep every guide in the same shape (section count range, step style, FAQ length) so a + morning format change is mechanical. +7. **Part C (`pi_compatible` removal):** do it only if the hub's controller floor is ≥ `0.315.0`. If not, + do nothing — **R-1067 already holds it**; do not open a second row. +8. Content rules from the spec stand, especially: no indexer, tracker or download-site names; nothing the + box already wires (`15-media-library.md` §6, §11); labels exactly as the app shows them at the pinned tag. + +## 3. One register item from the reviewer (felhom.eu) + +The 0.316.3 controller image contains another session's unreleased work (felhom-controller `CHANGELOG.md`, +v0.316.4 entry: „Do not deploy `0.316.3`"). That fact lives **only in the CHANGELOG**; the session said it +was filed with R-1081/R-1082, but neither row mentions it (checked 21:45 CEST). Open one row: +Category „Process & tooling", P3, owner CC — „Registry tag `felhom-controller:0.316.3` holds another +session's uncommitted code; it must never be offered to a box. Today the update button offers the highest +tag (0.317.0), so nothing reaches it — but any path that picks a lower or specific tag could." Name the paths +that choose a version (`09-update-architecture.md`) and say which, if any, could select 0.316.3. Do not +change code tonight. + +## 4. Report (catalog `REPORT.md`, overwritten; plain words first) + +1. What a household sees now: how many apps have a visible guide, how many hidden, how many not done. +2. The five pilot apps: label check and box check result each. +3. Gate change: tests and red-proofs. +4. Rows opened and closed (with the 0.316.3 row). Register size as four numbers. +5. Readings taken without asking (rule 1). +6. Observations: each `FILED: R-NNN` or `NOT-A-FINDING: `. + +--- +--- + +# APPENDIX — the full spec + +## Spec: App user guides — media pilot (5 apps), then the night batch (60 apps) + +--- + +## For the operator — what this does, in one page (plain language) + +**What is missing today.** A household that does not know an app has nowhere to look on the box. They +ask us. Each such question costs your time and does not scale. + +**What you get.** Every app gets a short user guide and an FAQ, in Hungarian and English. It shows on +the new "Útmutató" tab of the app page (built by the companion task). The text lives in the app +catalog, next to the app's other text, so it reaches every box with the normal catalog sync. + +**In what order.** +1. **Pilot, five apps — the media stack:** Plex, Sonarr, Radarr, Prowlarr, qBittorrent. Each guide is + checked twice: against the app's own source code at the exact version we ship, and on a real box. +2. **Night batch, the other 60 apps.** Same format. Each is checked against the app's source code. A + guide that fails the check stays hidden. Hidden means the box does not show it until a later + session fixes it. + +**Two rules you should know.** +- A guide shows on a box only when it records which app version it was checked against. When we + update the app later, the catalog warns that the guide may be stale. +- The media guides never name a download source, a tracker or an indexer site. Choosing one stays the + household's own choice (this is already the rule in `15-media-library.md`). The examples use free, + legal content. + +**What it costs you.** Tomorrow, read the Plex and the Sonarr guide on demo-hp. If the format is +wrong, we change it in all 65 files in one pass. + +**Nothing here touches customer data or a running box's apps, except throwaway installs on demo-hp.** + +--- + +## 0. Task class & scope + +- [x] **Implementation** — catalog content + one catalog gate change; checked live on demo-hp. + +**Repos touched:** +- [x] `app-catalog-felhom.eu` — `templates//.felhom.yml` (guide blocks), `scripts/check-copy-i18n.py`, + one advisory gate, CHANGELOG/REPORT/CONTEXT. +- [x] `felhom.eu` — `documentation/` (register rows, STATUS line, the onboarding checklist row). +- [ ] `felhom-controller` — NOT touched. It renders the guide from v0.315.0 + (the controller task of 2026-10-15; see §4 item 4). Older controllers ignore the unknown key + (`10-localisation.md` §7: the controller builds no strict YAML decoder), so the content may land + before the controller ships. + +--- + +## 1. Confirmed baselines (verified against live Gitea, 2026-10-15 ~17:00 CEST) + +| Repo | `main` @ commit | Version | +|------|-----------------|---------| +| app-catalog-felhom.eu | `e67aad4` | dated CHANGELOG (2026-10-15 evening, R-1058) | +| felhom-controller | `85f65c7` | `v0.314.0` (read only) | +| felhom.eu | `3263bb2` | docs | + +Pinned images at baseline (re-read before writing — they are what `checked_version` records): +`plexinc/pms-docker:1.41.4.9463-630c9f557`, `lscr.io/linuxserver/sonarr:4.0.20`, +`lscr.io/linuxserver/radarr:6.4.4`, `lscr.io/linuxserver/prowlarr:version-2.6.5.5623`, +`qbittorrentofficial/qbittorrent-nox:5.2.4-1`. + +**An unpushed change does not exist.** Commit directly to `main`. No branches. No `--no-verify`. + +--- + +## 2. Overview + +Add an `app_info.guide` block (schema below, identical to what the controller parses, §4 item 4) with an +`i18n.en` overlay to each template. Extend the catalog's copy gate so the guide is checked like all +other copy. Add one advisory gate that warns when a template's image tag differs from its guide's +`checked_version`. Write and check the five media guides (Part A), then the remaining 60 (Part B). +Remove `pi_compatible` from the catalog only if the floor allows it (Part C). + +--- + +## 3. Spike-first gate + +No unproven mechanism. The YAML copy model is measured (`10` §7). The one open question is +*how to check a guide without a browser* (none on DooPlex) — answered by method in §8, not by a spike. + +--- + +## 4. Read these files first + +1. `app-catalog-felhom.eu/CLAUDE.md`, `CONTEXT.md`, `NEW-APP-CHECKLIST.md` — conventions, the + pre-push gates (`catalog_gates.py --fast`), the gate decoys in `scripts/test_gate_decoys.py`. +2. `felhom.eu/documentation/architecture/10-localisation.md` §7 — the copy model and the copy gate + (`check-copy-i18n.py`, the `EN_MISSING_CEILING` ratchet). +3. `felhom.eu/documentation/architecture/15-media-library.md` §6 and §11 — **what the box wires by + itself** (qBittorrent categories, Sonarr/Radarr tag, root folder, download client, minimum free + space, Prowlarr → Sonarr/Radarr, Plex folders and scan). A guide never tells the household to do + what the box already did; it tells them it is done. Also: „Indexers stay the household's choice." +4. The schema and render rules AS BUILT in the controller (the earlier task file is not on disk): read + `felhom-controller` `internal/stacks/metadata.go` (`AppGuide`, `GuideSection`, `GuideFAQ`), + `metadata_i18n.go` (the overlay), `appinfo_address.go` (`DOMAIN` filled), and the guide tab template + (`templates/app_guide.html`). Rendered only when `checked_version` is set; plain text, no markdown, no HTML. +5. Source: `scripts/check-copy-i18n.py` (~L153–L160 base fields, ~L213–L230 overlay keys and the + "unknown key app_info.%s" refusal), `scripts/catalog_gates.py` (the gate table), + `templates/{plex,sonarr,radarr,prowlarr,qbittorrent}/.felhom.yml` (their current `first_steps`, + `prerequisites`, `after_start`). + +--- + +## 5. Existing functions / helpers to reuse + +| Symbol | Where | Use | Modify? | +|---|---|---|---| +| base-copy collector (`add("app_info.…")`) | `scripts/check-copy-i18n.py` | count guide strings as copy | Yes — Part 0 | +| overlay key whitelist (`if k not in ("tagline", …)`) | same | accept `guide` in `i18n.en.app_info` | Yes — Part 0 | +| `catalog_gates.py` gate table | `scripts/` | register the advisory guide-version gate (WARN only) | Yes — Part 0 | +| `scripts/test_gate_decoys.py` | `scripts/` | a decoy per new gate rule | Yes — Part 0 | + +**Do not reuse** `ladder.py` / `upgrade-test.py` style box drivers to install apps on Tester 1 or any +customer box — the pilot check runs on demo-hp only. + +--- + +## 6. Pattern references + +Existing `first_steps` / `i18n.en.app_info.first_steps` pairs in `templates/prowlarr/.felhom.yml` — +tone, tegező form („Nyisd meg…"), the `DOMAIN` placeholder. + +--- + +## 7. Integration scenarios (must pass) + +### Scenario A — the gate accepts a correct guide +Given `templates/sonarr/.felhom.yml` with a full HU guide and a full EN overlay, +When `catalog_gates.py --fast` runs, +Then it passes and the copy count includes every guide string (sections' title/intro/steps, FAQ q/a). + +### Scenario B — the gate refuses a broken guide (wrong case) +Given an EN overlay with `guide.checked_version`, or a section with an empty `steps`, or an FAQ entry +with `q` but no `a`, or an overlay with more sections than Hungarian, +When the gate runs, +Then it fails naming the template and the exact key. `checked_version` is not copy and may not be overlaid. + +### Scenario C — the version warning +Given Sonarr's guide says `checked_version: "4.0.20"` and the image moves to `4.0.21`, +When the gate runs, +Then it prints a WARN naming the template and both versions and **does not fail**. + +### Scenario D — a media guide does what it says +Given Sonarr installed on demo-hp from the live catalog, with the media links the box makes, +When each step of the Sonarr guide is followed through Sonarr's own API / served pages, +Then every menu name in the guide exists at the pinned version, every "the box already did this" +claim is true on the box, and no step is needed that the guide leaves out. + +### Scenario E — no source names (wrong case) +Given any of the five media guides, +When it is read, +Then it names no indexer, tracker or download site, in either language. A test enforces a deny-list of +the obvious names; the human rule is wider than the list. + +--- + +## 8. Rules for writing and checking a guide + +**Content.** +- Hungarian base, English overlay complete for every string (no `EN_MISSING_CEILING` increase). +- 3–6 sections, each a task the household wants ("Első film hozzáadása", "Telefonos app beállítása", + "Családtag hozzáadása"). One action per step. Short words. Adult tone, tegező form, no emoji. +- 4–8 FAQ entries: the questions a household will really ask (from the upstream FAQ/wiki/issues and + common forum questions). Each answer 1–3 sentences. +- Do not repeat `first_steps` (the tab shows them first). Do not describe what the box did except to + say it is done. Point at Felhom controls by their tab name where they apply (Plex code → + „Beállítások fül"). Use `DOMAIN` for the household's address (`