From cb00ff773c4089801a6aa1491c8760ab8bfb6bed Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Thu, 23 Jul 2026 13:26:12 -0500 Subject: [PATCH] Pin recursive-shape checked-cast failure paths in the dyncheck harness - a lying cast three knots deep renders the full path ($.children[0].children[0].label) --- tests/harness/dyncheck.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/harness/dyncheck.test.ts b/tests/harness/dyncheck.test.ts index a3c981a67..74a1db641 100644 --- a/tests/harness/dyncheck.test.ts +++ b/tests/harness/dyncheck.test.ts @@ -162,6 +162,23 @@ console.log("unreachable", d.server.host); ); }); + test("RECURSIVE shapes validate depth-first: the path names the deep offender", async () => { + // The named-recursive-shape walker calls itself per level (JSON input + // is a tree, so the recursion terminates); a failure three knots down + // still renders the full path. + const r = await compileAndRun( + "recursive-path", + `interface TreeNode { label: string; children: TreeNode[] } +const t = JSON.parse('{"label":"r","children":[{"label":"a","children":[{"label":7,"children":[]}]}]}') as TreeNode; +console.log("unreachable", t.label); +`, + ); + expect(r.exitCode).toBe(1); + expect(r.stderr).toContain( + "Uncaught TypeError: expected string at $.children[0].children[0].label, got number", + ); + }); + test("array where a record is expected names the mismatch at the root", async () => { const r = await compileAndRun( "root-kind",