Probing the foundation takeoff with hand-broken inputs showed seven shapes that crashed it instead of answering: a null body, interior as a string, piers as an object, null entries in interior, piers or footing.steps, and steps as an object. The command line and agent engine feed it parsed JSON, so a script that builds the input wrongly got a stack trace.
validateFoundation now checks shapes first and returns messages such as "interior must be a list". A new test runs eleven broken bodies and asserts an error list each time; all 19 foundation tests pass. Numeric strings like "480" are still coerced and accepted; I left that alone. No concrete maths changed.