--- id: playtest-tracker title: "The playtest tracker sheet — the tester-facing issue board" status: living source_sections: "Established 2026-08-14/15 (session housekeeping); supersedes the .txt handout as the primary feedback channel" related_topics: [operator-console, test-harness, project-overview] key_terms: [gitea, tracker, playtest] open_questions: - "Should the OPEN tab auto-sync from gitea on a schedule, or stay a manual reconciliation before/after each playtest?" --- # The playtest tracker sheet Since **2026-08-14** the testers track issues in a shared Google Sheet instead of the annotated `docs/OPEN_ISSUES_FOR_TESTERS.txt` handout. It is now the **primary feedback channel**; edited .txt docs and pasted Discord logs are secondary ([[operator-console]] covers the session tooling itself). The sheet is the testers' INPUT surface; **gitea remains the system of record.** ## Shape Two tabs. Sheet ID and the write-bridge credentials live in the operator's local Claude memory (`feedback-channels`), **never in this repo** — the bridge URL + token together grant write access to the sheet. - **OPEN** — `# | Priority | Test Status | Dev Status | Dev Comments | Tester Comments`, ONE row per ticket, sorted by priority then ticket number. - **CLOSED** — the same minus Priority, ascending by number. Also holds non-ticket records (completed audits) under a text key like `AUDIT`. **The split is driven by GITEA STATE, not by the Dev Status column** — the two drift constantly, and the sheet's own column is the stale one. ## Dev Status vocabulary (dev-owned column) The colour is **embedded in the label**, not applied as a cell fill: | Label | Meaning | |---|---| | `🟡 PATCHED - RETEST` | code landed, needs a playtest to confirm — the testers' retest list | | `🔴 FAILED RETEST` | a shipped fix did **not** hold; back on the bench (never collapse this into QUEUED — it understates a regression as "not started") | | `🟠 NEED INFO` | blocked on testers for a repro, detail, or log | | `🔵 YOUR CALL` | not a code question; needs their opinion or era memory | | `⚪ QUEUED` | logged and understood, work not started | | `🟢 WORKING` | actively being worked right now | | `✅ DONE` | verified — **only ever appears on CLOSED** | Priority: **P1** blocks a session / hits everyone · **P2** gameplay correctness confirmed in the field · **P3** presentation and polish · **P4** era question or opinion call · **P5** latent or internal with no field impact. Test Status is TESTER-owned (`Pass` / `Fail` / `Test` = not yet retested / `Rework` / `Clarify`). A **Fail on a ticket gitea has closed** is the highest-value signal in the whole sheet — it means a shipped fix did not hold, or the tested build predated it. ## The Dev Comments contract That column is what a player reads, so it is written for a player, in three lines: ``` STATUS: NEED FROM YOU: <- omit for QUEUED ``` Under ~55 words, no addresses, no engine jargon. The ask must name what to capture (which mech, which map, what time, what you expected vs saw, the boot-screen build number) — never "let us know if it happens again". If the thread already answers it, do not ask again. ## Working rules (learned the hard way) - **Read the gitea COMMENT THREAD, never the body alone.** Bodies are original reports and are routinely superseded, retracted, or already fixed by comment 4. Triaging 53 tickets from threads moved a third of the statuses and dropped P1 from 5 to 2. See [[reconstruction-gotchas]] for the general form of this mistake. - **Undated tester rows are historical.** Only rows explicitly prefixed with a date (`8/14 - `) came from that session. Reading undated carried-forward rows as fresh evidence produced a false "still crashing after the fix" report on #170 that had to be retracted across seven tickets. Ask testers to date entries. - **Never write `DONE` on OPEN.** A row that is done belongs on CLOSED; a `DONE` on the open page is a contradiction that confuses everyone reading it. - **Merge duplicates to one row per ticket** — linking loose reports to existing tickets creates two rows for the same number otherwise. - **Never use cell fills for status.** Fills belong to cells, labels to text; every re-sort moves the text and leaves the paint, so they desync. This was re-fixed three times before the colour was embedded in the label. - **A leftover FILTER hides rows after a rewrite** — if rows appear to vanish and the row numbers in the gutter SKIP, that is hidden rows, not lost data (Data → Remove filter). - **Row heights**: autofit makes wrapped comment rows hundreds of pixels tall (≈4 visible rows). Pin to ~63 px. ## The cycle 1. **Before a playtest** — regenerate/refresh: reconcile every row against gitea, clear stale statuses, make sure each `NEED INFO` carries an ask the testers can act on that night. 2. **After a playtest — THE SWEEP.** Read the sheet, file the unfiled `New` rows as tickets, link duplicates to existing numbers, post the field evidence onto the tickets, then resolve every `🟡 PATCHED - RETEST` row by what the tester wrote in Test Status: | Test Status | Meaning | Action | |---|---|---| | `Pass` | fix confirmed | close in gitea, move the row to CLOSED | | `Fail` + detail | the fix did not hold | `🔴 FAILED RETEST`, reopen in gitea, raise to ≥P2, post their evidence | | `Fail`, no detail | cannot act yet | `🟠 NEED INFO` with ONE discriminating question | | blank | nobody tested it | leave `🟡`, roll to the next session | ⚠ **A Pass or Fail with no BUILD NUMBER is uninterpretable** — a Pass on an older build cannot verify a fix that shipped later. Before treating a `Fail` as a regression, establish that the tested build actually contained the fix; that ambiguity is why #27 and #38 sat at `NEED INFO` (asking for the boot-screen build) rather than going straight to `🔴`. Stamp "shipped in build NNN" into every `🟡` Dev Comment so the answer is checkable later. 3. Reconciling ~50 tickets against their threads is a fan-out job — one agent per batch of ~7, returning `{num, dev_status, priority, dev_comment}`. ## Access - **Read** — the sheet is public, so the CSV export works with no auth: `https://docs.google.com/spreadsheets/d//export?format=csv&gid=0` (307-redirects to a `googleusercontent.com` host; follow it). The Claude **Google Drive connector cannot see it** — that connector is scoped to files it created itself, and it has no cell-write capability for any file, so sharing the sheet to the account does not help. - **Write** — a Google Apps Script web app bound to the sheet, called with `curl -sL -d` (never `-X POST`). Actions: `ping`, `tabs`, `get`, `set`, `append`, `note`, `width`, `height`, `autofit`, `format`. Extending it requires re-pasting the script AND **Deploy → Manage deployments → pencil → Version: New version** — clicking Deploy alone keeps the old code live on the same URL. Treat further script edits as expensive: the operator has said the redeploy loop is not worth repeating for cosmetics. ## Key Relationships - Feeds: the gitea tracker (system of record) · `docs/OPEN_ISSUES_FOR_TESTERS.txt` (now secondary) - Uses: [[operator-console]] (session tooling) · [[test-harness]] (what "verified" means here)