0b1b39f829
The CLI help text claimed `render` was symmetric to `parse`, but `render` was wired to ailang_core::pretty::module (an older human-pretty form) while `parse` consumed form (A). Two different "text projections" coexisted under one name. Fix: Cmd::Render and Cmd::Describe (both branches) now call ailang_surface::print, the actual inverse of `parse`. Round-trip gate via `ail render | ail parse` is now an e2e test in crates/ail/tests/e2e.rs in addition to the existing unit-level round-trip across all 25 fixtures in ailang-surface/tests. Cleanup: `ailang_core::pretty::module` and its three private helpers (`def_block`, `term_block`, `term_inline`) deleted — ~260 LOC of duplicate-purpose code removed. pretty.rs goes from 457 to 196 LOC. Surviving surface is intentionally narrow: manifest, type_to_string, pattern_to_string — the diagnostic stringification used in error messages, where one-line ML notation reads better than form (A)'s nested S-expressions. Module-level doc rewritten to nail down the single-purpose framing. Tests: 89/89 (e2e +1, ailang-core unit -1 since the deleted test exercised the deleted fn). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>