feat: Stress it beat for Modules 6-10, Module 11 (Break your own engine), level solver tool

- lessons 8 and 9 updated for the once-per-move rule, per-object negated
  conversion and the new ordering tests
- tools/solve-spellgrid.mjs: breadth-first search over a SpellGrid level
  with the TypeScript reference; --never-rule and --naive
- README, harness.md and the mentor skill know the new beat and module

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Fable 5.2 committed 2026-11-11 09:32:22 +01:00
1 parent e907f17937
commit 4cb0f3a61f
13 files changed
+771 -19

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { toolsDir } from "./helpers.mjs";
import { parseArgs } from "../solve-spellgrid.mjs";
test("solve_spellgrid_parses_args", () => {
assert.deepEqual(parseArgs([]), { level: "l1", dir: null, solver: [] });
assert.deepEqual(parseArgs(["l3", "--naive", "--max", "9", "--dir", "x", "--never-rule", "A IS B", "--all"]), {
level: "l3",
dir: "x",
solver: ["--naive", "--max", "9", "--never-rule", "A IS B", "--all"],
});
});
test("solve_spellgrid_solver_uses_only_the_harness", () => {
// The solver is copied into a staged reference: it may import the harness and nothing else of the engine.
const path = join(toolsDir, "solver", "solve.ts");
assert.ok(existsSync(path));
const imports = [...readFileSync(path, "utf8").matchAll(/from "([^"]+)"/g)].map((m) => m[1]);
assert.deepEqual(imports.sort(), ["./src/harness", "node:fs"]);
});