feat: module 05 assemble

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 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-29 03:17:21 +01:00
1 parent 55fe5a71d7
commit e04dc1a11f
73 files changed
+6010 -9

No files matched your search

+4 -1
View File
@@ -1,10 +1,11 @@
#!/usr/bin/env node
// For each module <= N with a reference/: copy reference + tests of modules 01..module into a temp dir, run tests.
// course/cards (the card data, loaded by the references from Module 5) is staged as <dir>/cards.
import { cpSync, existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { basename, join } from "node:path";
import { moduleDirs, testFiles, fail } from "./lib.mjs";
import { courseRoot, moduleDirs, testFiles, fail } from "./lib.mjs";
// A staged reference has no node_modules, so TS installs the reference's own
// pinned devDependencies first (a bare `npx vitest` would fetch an unrelated version).
@@ -35,6 +36,8 @@ export function stage(plan, lang) {
for (const t of plan.testModules) {
for (const f of testFiles(t.path, lang)) cpSync(f, join(dir, "tests", basename(f)));
}
const cards = join(courseRoot(), "cards");
if (existsSync(cards)) cpSync(cards, join(dir, "cards"), { recursive: true });
return dir;
}