docs(daily): reconcile wildcard counts across guide + schema; pool 12->11

Self-review of the wildcard authoring spec caught two real issues:

1. Count contradiction: the new Wildcard section said '+12 free' while the pack's
   authoritative counts (QUESTION_SCHEMA.md daily table + metadata, and the guide's
   Required Counts + Final Production Gate 'count validation') still said 500/75. A
   content agent running count validation would fail, or worse delete weekday
   questions to hit 500. Reconciled all four locations to the weekday pack (frozen
   500) + wildcard add-on -> 511 total / 86 free / 425 premium, and folded the
   wildcard set into the Final Production Gate review sampling.

2. Rotation math: the picker indexes epochDay % poolSize and wildcard days fall ~10
   apart, so a pool size sharing a factor with 10 (12 is even) only surfaces a
   fraction of the questions per year. Pool size must be coprime with 10 -> 11, not
   12. Documented as a hard constraint so it isn't 'rounded to 10' later.

Also hardened the section: net-new (not a patch), answer_config option mirror,
unique snake_case option ids, and a QUESTION_SCHEMA.md cross-reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
null 2026-07-11 16:48:18 -05:00
parent f74f0e96f5
commit d3763fd37b
2 changed files with 57 additions and 20 deletions

View File

@ -30,13 +30,23 @@ Use the old file name only while the app code still expects it. The content insi
This special daily pack uses: This special daily pack uses:
* 500 total questions **Weekday pack (frozen — do not change these 500):**
* 75 free questions
* 425 premium questions * 500 total weekday questions
* 75 free weekday questions
* 425 premium weekday questions
* 500 single_choice questions * 500 single_choice questions
* 4 options per question preferred * 4 options per question preferred
* 4 to 6 options allowed * 4 to 6 options allowed
**Wildcard add-on (new — see the Wildcard Mode section):**
* 11 free single_choice wildcard questions (free only; pool size must stay coprime with 10)
**New pack totals with the wildcard add-on:**
* 511 total · 86 free · 425 premium · 511 single_choice
Do not apply the standard 250 question category mix to this pack. Do not apply the standard 250 question category mix to this pack.
## Required Type ## Required Type
@ -579,16 +589,23 @@ quick, warm, PG-13 max on the free tier, 4 options preferred (46 allowed), si
### Wildcard counts ### Wildcard counts
* **12 free** `single_choice` wildcard questions. **Free only** — the daily picker never draws from * **11 free** `single_choice` wildcard questions. **Free only** — the daily picker never draws from
the premium pool, so premium wildcards would never be served. Do not author premium wildcards. the premium pool, so premium wildcards would never be served. Do not author premium wildcards.
* This is **in addition** to the existing 500 (75 free + 425 premium) weekday questions. * Added on top of the existing 500 weekday questions → new pack totals **511 total · 86 free ·
425 premium** (the "Required Counts" section above is updated to match).
* **Why 11, not 10 — this is a correctness constraint, not a preference.** Wildcard days fall ~10
days apart (day-of-year mod 10 == 3) and the picker indexes `epochDay % poolSize`. A pool size that
shares a factor with 10 (i.e. divisible by 2 or 5 — e.g. 10 or 12) collapses the rotation, so only
a fraction of the questions ever appear in a given year. **The wildcard pool size must be coprime
with 10** (9, 11, 13, …). 11 gives full rotation with good freshness — do not round it to 10.
### Wildcard IDs ### Wildcard IDs
Continue the existing sequence so ids stay sortable and unique — the picker sorts by id: Continue the existing sequence so ids stay sortable and unique — the picker sorts by id (the pack
currently ends at `_500`, no gaps):
```text ```text
daily_single_choice_weekly_v1_501 … daily_single_choice_weekly_v1_512 daily_single_choice_weekly_v1_501 … daily_single_choice_weekly_v1_511
``` ```
### Wildcard tags (EXACT — this is an app contract) ### Wildcard tags (EXACT — this is an app contract)
@ -641,11 +658,22 @@ weekday `mode_*` tag (a weekday mode tag would wrongly pull the wildcard into th
} }
``` ```
### Wildcard authoring rules (easy-to-miss)
* These 11 are **net-new** questions, not a patch. "Patch Discipline: Fix Only What Fails" freezes the
existing 500 — it does not stop you creating the new wildcard set. Do not renumber or edit any 001500.
* `options` must be **mirrored exactly** into `answer_config.options` (same ids, same text, same order)
with `"selection_style": "single"` — the app reads the options from `answer_config`.
* Option `id`s are lower_snake_case and **unique within the question**.
* `access` is `"free"` for all 11 (there is no premium wildcard).
* Field schema, types, and validation rules live in `QUESTION_SCHEMA.md`; tone/voice gates live above in
this guide (Daily Fun Gate, Option Quality Standard, Banned Tone Words). Wildcard is held to the same bar.
### After the JSON is authored — engineer rollout (NOT the content agent's job) ### After the JSON is authored — engineer rollout (NOT the content agent's job)
Once the 12 wildcard questions are in `daily_fun_multiple_choice_v3.json`, an engineer lands them: Once the 11 wildcard questions are in `daily_fun_multiple_choice_v3.json`, an engineer lands them:
1. **Asset DB:** insert the 12 rows into `app/src/main/assets/database/app.db` `question` table 1. **Asset DB:** insert the 11 rows into `app/src/main/assets/database/app.db` `question` table
**data-only** (`category_id='daily_fun_mc'`, `status='active'`, `is_premium=0`, `tags` containing **data-only** (`category_id='daily_fun_mc'`, `status='active'`, `is_premium=0`, `tags` containing
`mode_wildcard`). **Do NOT run `build_db.py`** — a full rebuild changes the Room identity hash and `mode_wildcard`). **Do NOT run `build_db.py`** — a full rebuild changes the Room identity hash and
breaks the shipped DB (see project notes). Data-only inserts are safe. breaks the shipped DB (see project notes). Data-only inserts are safe.
@ -796,14 +824,14 @@ These sources informed the daily fun rules. Do not copy their question lists. Us
Before shipping: Before shipping:
1. Run schema and count validation. 1. Run schema and count validation against the totals in Required Counts (511 · 86 free · 425 premium once the wildcard add-on is in; 511 single_choice).
2. Run duplicate question checks. 2. Run duplicate question checks.
3. Run duplicate option-list checks. 3. Run duplicate option-list checks.
4. Check repeated openers and repeated option text. 4. Check repeated openers and repeated option text.
5. Read 10 random questions from each weekday. 5. Read 10 random questions from each weekday, plus all 11 wildcard questions.
6. Mark anything therapy-coded, boring, weird, logistical, or not fun. 6. Mark anything therapy-coded, boring, weird, logistical, or not fun. For wildcard specifically, also mark anything tied to a particular weekday/day-name (wildcard must read on any day).
7. Fix the marked items. 7. Fix the marked items.
8. Run a second random sample from each weekday. 8. Run a second random sample from each weekday, and re-read the wildcard set.
9. Fix only the newly marked sample items. 9. Fix only the newly marked sample items.
10. Run the second sample again if any sampled item changed. 10. Run the second sample again if any sampled item changed.
11. Ship only when the second sample passes cleanly and the remaining hard flag count is 0. 11. Ship only when the second sample passes cleanly and the remaining hard flag count is 0.

View File

@ -180,15 +180,24 @@ Compatibility file name:
daily_fun_multiple_choice_v3.json daily_fun_multiple_choice_v3.json
``` ```
Target counts: Target counts — weekday pack (frozen; do not change these 500):
| Field | Count | | Field | Count |
|---|---:| |---|---:|
| total | 500 | | weekday total | 500 |
| free | 75 | | weekday free | 75 |
| premium | 425 | | weekday premium | 425 |
| single_choice | 500 | | single_choice | 500 |
Plus the wildcard add-on (surprise days; see `DAILY_SINGLE_CHOICE_WEEKDAY_SYSTEM.md` → Wildcard Mode).
The wildcard pool size must stay **coprime with 10** (the wildcard-day spacing), so 11, not 10/12:
| Field | Count |
|---|---:|
| wildcard free | 11 |
**New pack totals (weekday + wildcard):** 511 total · 86 free · 425 premium · 511 single_choice.
These counts do not apply to standard category packs. These counts do not apply to standard category packs.
## Daily Pack Metadata Example ## Daily Pack Metadata Example
@ -198,9 +207,9 @@ These counts do not apply to standard category packs.
"id": "daily_single_choice_weekly_v1", "id": "daily_single_choice_weekly_v1",
"title": "Daily Single Choice", "title": "Daily Single Choice",
"access": "mixed", "access": "mixed",
"description": "One weekday themed single choice question per day.", "description": "One weekday themed single choice question per day, plus wildcard surprise days.",
"count": 500, "count": 511,
"free_count": 75, "free_count": 86,
"premium_count": 425, "premium_count": 425,
"question_type_policy": "single_choice_only", "question_type_policy": "single_choice_only",
"review_policy": "weekday_batch_loop_required", "review_policy": "weekday_batch_loop_required",