feat: log tree from Module 2 (logTree / log_tree); SpellGrid CLIs print Log:

Engine events carry the nesting depth they were recorded at; the harness
prints the log as an indented tree. New tests test_02_log_tree_shows_nesting
and test_03_log_tree_death_phase; both SpellGrid CLIs print the tree of the
last command's Sequences under a Log: line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-11-11 10:23:59 +01:00
1 parent 06a1b34c5d
commit 97c64ebee8
86 files changed
+1375 -55

No files matched your search

@@ -24,6 +24,29 @@ test("cli_wins_level_2_with_choices_and_play", () => {
expect(out).toContain("Hand: Ember Moth (Assembled)");
});
test("cli_prints_the_log_tree_of_each_command", () => {
const { out } = play("l1-double-tap", ["w", "w", "c Whirlwind", "q"]);
// The moves run no Sequence, so only the cast prints a log: its tree, Deathrattles nested.
expect(out.split("Log:\n")).toHaveLength(2);
expect(out).toContain(
[
"Log:",
'SpellCast{card: "Whirlwind"}',
"Damaged{target: 32, amount: 1}",
"Damaged{target: 33, amount: 1}",
"Destroyed{id: 32}",
"DeathPhase{round: 1}",
'Triggered{source: 32, trigger: "deathrattle"}',
" Damaged{target: 33, amount: 1}",
'Triggered{source: 32, trigger: "deathrattle"}',
" Damaged{target: 33, amount: 1}",
"Destroyed{id: 33}",
"DeathPhase{round: 2}",
"",
].join("\n"),
);
});
test("cli_reports_errors_and_quits", () => {
const { outcome, out } = play("l3-simultaneous-paradox", ["c Spark", "x", "q"]);
expect(outcome).toBe("quit");