# Classroom Puzzle Kits - Build Plan

Session: 2026-07-08, autonomous (Ralph out ~3h; plan-first waived this session only, full build authority granted).
Ground rules in force: canon/data/ is the ONLY content source and is READ-ONLY; work exclusively in products/puzzle-kits/; never write to canon/; no review-server clicks; no git push; hyphens not em-dashes in any text I author (canon-verbatim strings keep their printed punctuation, including em-dashes).

## Objective

Printable classroom puzzle kits (PDF) built from the promoted canon graph:
- 14 book kits (Book 1 through Book 14; Book 12 = volumes b12a + b12b, one story)
- 2 theme kits ("Moves and Scallywags", "Gadgets and Codes")
- Every kit ends with an answer key citing record ids and book:chapter:page refs
- REPORT.md (what was built, stats, verification results) and OPEN_QUESTIONS.md (everything needing Ralph's review, especially all instructional text)

## Content provenance rules (the heart of it)

1. Puzzle CONTENT is canon-verbatim: strings are copied by code, never typed by the model, from these canon/data fields only:
   - entities: name, aliases, description_as_written, type
   - facts: quote (preferred), assertion (fallback, flagged - it is adjudicated canon wording but not printed book text)
   - relationships: evidence_quote
   - incidents: label
2. Permitted mechanical transformations (each recorded per item and machine-verifiable):
   - BLANKING: one word of a canon string replaced by underscores (fill-in-the-blank); reconstruction must equal the original string exactly.
   - SUBSTRING: a canon quote split at a printed delimiter (e.g. KB-15 flash-code lines split at ":" into pattern/meaning; the "Weekday (Title)" per-book segments of f_al1_399). Both halves must be verbatim substrings of the source string.
   - LETTERIZATION: word-search grid entries are the name uppercased with non-letters dropped (standard word-search practice); the printed word LIST shows the canon name verbatim.
   - ENCODING: Morse / NATO-phonetic renderings of canon names for code-breaking pages. The books themselves use the real international systems (f_b01_010/011: Dash = "Delta Alpha Sierra Hotel", "-../.-/ ... /...."; f_al1_300: Rob = "Romeo Oscar Bravo", ".-./---/-..."), so the standard tables are canon-consistent; those canon facts are cited on every code page as the in-world anchor.
3. Instructional text (puzzle directions, headers, decoder-table labels) is functional, minimal, and NOT book voice; the complete inventory of instructional strings goes to OPEN_QUESTIONS.md for Ralph's review. No invented story text anywhere.
4. Citation key per puzzle: every item's answer-key entry lists the record id (f_/e_/r_/i_) and its refs, rendered both raw (b01:c02:p045) and human-readable (Book 1, ch. 2, p. 45).
5. Word-search filler letters, shuffle orders, and grid placements are deterministic (fixed RNG seed per kit) so kits are reproducible byte-for-byte.
6. Non-encodable content (outside WinAnsi, e.g. CJK strays) is skipped and logged, never transliterated silently.

## Kit contents (book kits)

Page 1 - Cover: kit label ("Total Mayhem Puzzle Kit - Book N"), contents list, source note. For Books 1-7 the cover also prints the canon weekday+title segment quoted verbatim from f_al1_399 [al1:c00:p003]. Books 8-14 have no canon title record - flagged in OPEN_QUESTIONS.
Page 2 - Word Search: 12-16 entity names from that book (characters, places, gadgets), 15x15 grid, 8 directions; each listed word verified to appear exactly once.
Page 3 - Match-Up: ~10 pairs, entity name <-> description_as_written (descriptions containing the entity's own name are excluded so answers are not given away).
Page 4 - Fill in the Blanks: ~8 canon quotes with one word blanked + shuffled word bank (the bank is exactly the set of blanked canon words - no invented distractors).
Page 5 - Code-Breaking: decode canon names from Morse and NATO phonetic (standard tables printed as reference, canon anchor facts cited); kits whose book carries KB-15 flash-code facts also get a flash-pattern <-> meaning matching block.
Page 6+ - ANSWER KEY: every solution with record id + refs.

Theme kit "Moves and Scallywags": Move # <-> move name matching (from the 53 Move entities), move-description fill-in-the-blanks, scallywag stats quiz (numeric facts, number blanked), scallywag-type word search.
Theme kit "Gadgets and Codes": KB-15 flash-code matching, Morse/NATO decoding of gadget names, gadget <-> inventor matching (invented_by relationships, evidence_quote cited), gadget word search.

## Pipeline (products/puzzle-kits/tools/)

- canon_lib.py - load + index canon/data (read-only), ref parsing/formatting, WinAnsi checks
- select_content.py - deterministic per-kit selection heuristics -> content/<kit>.json (records used, field used, transformation used)
- puzzle_gen.py - word-search placement/fill (seeded, uniqueness-verified), blanking, pair shuffling, Morse/NATO encoding -> puzzles embedded into content/<kit>.json
- pdflib.py - minimal dependency-free PDF writer (US Letter, core fonts Courier/Courier-Bold, WinAnsi encoding, text + lines + boxes). reportlab is not installed and the project keeps tooling dependency-free; puzzle pages are text and grids, well within a hand-rolled writer.
- render_kit.py - lay out puzzle pages + answer key -> kits/*.pdf
- verify_kits.py - provenance audit: every content string in every kit must trace to its cited canon record under the declared transformation; citation ids must exist; refs must match the record. Results go in REPORT.md.
- build_all.py - orchestrates everything.

QA: verify_kits.py (provenance) + pdftotext extraction smoke test + pdftoppm render spot-checks read visually.

## Commit strategy

Local only, narrow pathspecs (`git add/commit -- products/puzzle-kits`), commit at each milestone: plan, tools, content, kits, report. Never git add -A (parallel product sessions share the index).

## Milestones

1. PLAN.md committed (this file)
2. canon_lib + selection + generators producing content/*.json for all 16 kits
3. pdflib + renderer producing kits/*.pdf
4. verify_kits clean + REPORT.md + OPEN_QUESTIONS.md
5. Final commit + session summary for Ralph
