--- 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. - **DATE EVERY TESTER ENTRY: `M/D - ` at the front of each line.** The build is cut per session, so the date implies the build — which is what makes a Pass or Fail interpretable at all. Entries carried over from before this convention are marked **`(undated)`**, meaning *provenance unknown — do not treat as fresh evidence*. That marker is deliberate: the sheet was seeded from earlier tracking and nobody can now say which rows are original, so stamping them all with the session date would manufacture precision. Reading undated rows as fresh already produced a false "still crashing after the fix" claim on #170 that had to be retracted across seven tickets — #170's row carries the same three timestamps and players as its own 2026-08-12 body, and whether that is a copy-forward or a genuine recurrence is STILL UNRESOLVED. One entry per line, each with its own stamp; comment cells grow over time and undated text running together is unreadable within two sessions. An undated entry CAN often be dated from gitea: if its text is quoted in a ticket body, the report existed by that ticket's creation date (this is how #170's three crash lines were pinned to 2026-08-12 — its body says `FIELD 2026-08-12` and lists those exact times). ⚠ **SELF-REFERENCE TRAP:** do not date an entry from a comment YOU wrote while harvesting the sheet — those quote the tester text verbatim, so a naive search dates the report to your own housekeeping. Exclude same-day comments and take the EARLIEST match. This bit once already: a #170 line was briefly stamped with the harvest date instead of the event date. - **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)