I1: run-scenario and both SpellGrid CLIs check moves first and treat any other engine error as fatal (same text in both tracks); trigger blocks close on error (try/finally, catch_unwind in Rust); unknown summons rejected. I2, I3, M1-M7, T3, T9a-c, T10a-b. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Course website
Astro Starlight site built from the lessons in course/.
Run locally: npm ci && npm run dev (from this directory), then open http://localhost:4321.
npm run sync (run before dev and build) generates two git-ignored directories, so nothing is copied by hand:
src/content/docs/course/: one page percourse/*/lesson.md, andcourse/harness.md.src/game/generated/: the play page's game. The TypeScript reference of the highest module that has one (engine/,harness.ts,content/), copied unmodified, except thatcontent/index.ts(which reads the cards withnode:fs) is replaced by one that re-exportssrc/game/content.browser.ts; pluscards.jsonandlevels.json, which that module imports statically.
The play page (/play/, src/pages/play.astro) is SpellGrid in the browser. src/game/session.ts holds the harness and the list of inputs (Undo replays them; Assemble's questions are answered by replaying with one more answer), and src/game/play.ts draws it. Neither knows a rule. The page uses the highest module's reference (Module 12 today), while course/10-spellgrid/levels/proofs.json and the tools that check it (the solver, verify-levels) stage Module 10's: the proofs are about the Module 10 engine. On the ten levels the two play the same game, because no level writes a condition (Module 11) and SpellGrid has no attack input (Module 12). scripts/game.test.mjs loads the same files under plain Node and plays Level 3 to the win (npm run test:site from the repository root; Node 22.15 or later, for module.registerHooks).
A lesson links to a site page by its source file, such as [Play SpellGrid](../../site/src/pages/play.astro): the sync rewrites that to /play/, and the link still works on the repository's web view.
COURSE_HOST (e.g. course.example.com) sets the public site URL at build time. Unset, the site uses http://localhost:4321. Deploys must set it; see ../deploy/README.md.