- verify-references --expansion overlays expansion/solution on each reference and runs the
cumulative tests plus the drop test; refuses a solution that touches src/engine/
- CI job verify-expansions
- README: workspace-template + git init step, tool list, repo disclaimer link
- Cargo.lock for every Rust reference (staged with the reference, pins serde for rustc 1.85.1)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Lesson 10 and both M10 reference READMEs now give the real recipe
(node tools/play-spellgrid.mjs <rust|ts> [l1|l2|l3]); root script play:spellgrid.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- cardDirs: course/cards only from Module 5 (spec 6.2a); fixture modules 04/05 and tests
- coupling-audit: noun words match as UPPERCASE, PascalCase or a whole string literal;
lowercase identifiers like key/flag pass; card names keep every variant
- isMain() argv guard replaces import.meta.main in coupling-audit and verify-references;
engines.node >=22
- expansion-check: git diff --no-renames so moving engine code into content fails
- start-module and other tools: clear error when .course.json is missing
- check-links: malformed URLs reported as invalid URL instead of throwing
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Re-verify Teikari article quotes and GDC speaker, soften unsourced
claims (lessons 01, 06, 07, 10), add course-simplification bullets to
lesson 07's differs box, qualify OPEN obstruction wording in research,
and add tools/check-links.mjs (report-only) with npm run check:links.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- SpellGrid cards move to course/10-spellgrid/cards; start-module and
verify-references stage course/cards plus module-local cards up to the module,
so M5-M9 workspaces get exactly the pre-M10 card set.
- cast() rejects a chosen-target spell without a target (checkCast/checkPlay);
new test_10_targeted_spell_needs_target.
- Rust CLI pre-validates instead of swapping the global panic hook.
- Catalog: CRIER noun; DEATHRATTLE/BATTLECRY note on lexicon vs catalog role.
- Lesson: design note on mid-movement reparse.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SpellGrid capstone: Part I's card engine and Part II's grid engine joined at
three seams (rules -> aura data, hazard victims -> one destroy Sequence,
Sequence end -> write text, remove the dead, reparse). Three levels with
scripted solutions, a naive-timing test via a harness-only hook that
reverses the END_OF_PHASE list, CLIs in both tracks, the BATTLECRY IS DOUBLE
Expansion Drop, SpellGrid cards and words in course/cards and the catalog,
level schema cards/hand, and tools staging/copying of module levels.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Movement planned in full, then committed: a Planner builds a plan
(moving and destroyed ids) by running content's movement responses
(OPEN/SHUT, PUSH, STOP) for every step, rolling back failed branches.
Edge of level blocks; YOU objects move furthest-ahead first; rules are
reparsed once after movement. Harness: move/move_dir(Dir), posOf,
kindsAt. Expansion Drop: PULL as one word plus one content response.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Adds IS NOT to the Part II parser and a resolution pass (negation, then
identity lock) that turns parsed rules into the rules in force; harness
gains activeRules() and hasProperty(). A leading NOT now breaks the
sentence instead of being ignored (carried from M6 review). Nouns say
which objects they name ("selects"), so the ALL Expansion Drop is one
line of data. Corrects lesson 06's NOT wording; harness.md M7 details.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
First Part II module. The cumulative reference adds a second engine
(src/engine/puzzle: grid, lexer, parser) beside Part I's; nouns and
properties are data in src/content/words.json, and the engine names only
IS/AND/NOT/TEXT and the base rule TEXT IS PUSH. Rules are recompiled from
the board on every change; rules() is a sorted set. Adds the M6 scenarios
and tests (rows, columns, shared IS, AND distribution, stacked text, base
rule), the HOT word as a data-only Expansion Drop, the lesson with the
Part II bridge, and the Rust LevelDef shape in harness.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cards become JSON data in course/cards (one file per card, validated
against card.schema.json and the catalog); the M5 references load them
via registerCards and interpret effects, replacing content closures.
Adds assemble(base, donor, half), the assemble/buffHand effects with an
injected chooser, Fleshshape as the data-only Expansion Drop, and stages
course/cards in verify-references and start-module.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Trigger multipliers as aura data on cards, snapshotted by an Aura Update
(Other) after each Death Creation Step and on summon, and applied by one
generic routine (activations) when each queued trigger starts. Baron
Rivendare is content only (stacking "max"); Brann Bronzebeard is the
content-only Expansion Drop. Adds play (now required) and Battlecry.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Deferred death: damage and destroy only mark minions; the Death Creation
Step removes them when the outermost Phase ends, and Death Phases resolve
Deathrattles in order of play until no new deaths occur. Deathrattle
summons use the board position the Death Event remembered. Harness adds
destroy(target). Expansion Drop: Twisting Nether as content only.
test_02_mortally_wounded_still_triggers no longer asserts the Acolyte is
still on the board: from Module 3 on it leaves at the end of the Sequence,
and verify-references runs Module 2's tests against the Module 3 reference.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
verify-references ran a bare `npx vitest run` in the staged reference, which
fetched an unrelated vitest that could not load the reference config. It now
installs the reference's devDependencies first. sync-check also checks each
module's expansion/tests against ### headings in expansion/README.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Naive engine in Rust and TypeScript (immediate damage, inline triggers,
recursive Deathrattles, cards defined in the engine) with
test_00_naive_runs and the expected-fail test_00_real_rules_whirlwind_order,
plus the Module 0 lesson.
Co-Authored-By: Claude Opus 5.5 <[email protected]>